ucg/std/lists.ucg

89 lines
2.6 KiB
Plaintext
Raw Normal View History

// Joins a list into a string with an optional provided separator.
// The string will be in the result field of the generated tuple
// from the module.
let str_join = module{
// The default separator is a single space. You can override
// this when you call the module if desired.
sep=" ",
// The list is a required parameter.
list=NULL,
} => (result) {
// The function used by reduce to join the list into a string.
let joiner = func (acc, item) => select (acc.out == ""), NULL, {
true = acc{
out="@@" % (acc.out,item),
},
false = acc{
out="@@@" % (acc.out, acc.sep, item),
},
};
// The resulting joined string. Reference the result field from the
// tuple the module produces to get the joined string.
let result = reduce(joiner, {sep=mod.sep, out=""}, (mod.list)).out;
};
// Computes the length of the provided list.
let len = func(list) => reduce(func(acc, item) => acc + 1, 0, list);
// Reverses the provided list.
let reverse = func(list) => reduce(func (acc, item) => [item] + acc, [], list);
// Enumerates the provided list with optional start and step parameters for the
// enumeration. Prodices a list of pairs with the numeration and the list item.
//
// enumerate{list=["a","b","c"]}.result == [[0, "a"], [1, "b"], [2, "c"]]
let enumerate = module{
// Where to start the enumeration.
start = 0,
// The step amount for each enumeration.
step = 1,
// The list to enumerate.
list = NULL,
} => (result) {
let reducer = func (acc, item) => acc{
count = acc.count + acc.step,
list=acc.list + [[acc.count, item]],
};
let result = reduce(
reducer,
{count=mod.start, list=[], step=mod.step},
(mod.list)).list;
};
// zips two lists together.
//
// zip{list1=[0,2,4],list2=[1,3,5]}.result == [[0, 1], [2, 3], [4, 5]]
let zip = module{
list1 = NULL,
list2 = NULL,
} => (result) {
let len = import "std/lists.ucg".len;
// Compute the length of each list.
let len1 = len(mod.list1);
let len2 = len(mod.list2);
// Compute the min range of the two lists.
let rng = select (len1 >= len2), NULL, {
true = 0:(len1 - 1),
false = 0:(len2 - 1),
};
// The reducer function for the zip operation.
let reducer = func (acc, item) => acc{
result = acc.result + [[acc.list1.(item), acc.list2.(item)]],
idxs = acc.idxs + [item]
};
let acc = {
list1 = mod.list1,
list2 = mod.list2,
result = [],
idxs = [],
};
// The resulting zipped list.
let result = reduce(reducer, acc, rng).result;
};