2019-02-04 20:29:04 -06:00
|
|
|
// 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.
|
2019-01-08 20:32:16 -06:00
|
|
|
let str_join = module{
|
2019-02-04 20:29:04 -06:00
|
|
|
// The default separator is a single space. You can override
|
|
|
|
// this when you call the module if desired.
|
2019-01-08 20:32:16 -06:00
|
|
|
sep=" ",
|
2019-02-04 20:29:04 -06:00
|
|
|
// The list is a required parameter.
|
2019-01-08 20:32:16 -06:00
|
|
|
list=NULL,
|
2019-02-24 08:16:07 -06:00
|
|
|
} => (result) {
|
2019-02-04 20:29:04 -06:00
|
|
|
// The function used by reduce to join the list into a string.
|
2019-01-24 20:04:40 -06:00
|
|
|
let joiner = func (acc, item) => select (acc.out == ""), NULL, {
|
2019-01-16 19:07:03 -06:00
|
|
|
true = acc{
|
|
|
|
out="@@" % (acc.out,item),
|
|
|
|
},
|
|
|
|
false = acc{
|
|
|
|
out="@@@" % (acc.out, acc.sep, item),
|
2019-01-08 20:32:16 -06:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// The resulting joined string. Reference the result field from the
|
|
|
|
// tuple the module produces to get the joined string.
|
2019-01-31 16:33:12 -06:00
|
|
|
let result = reduce(joiner, {sep=mod.sep, out=""}, (mod.list)).out;
|
2019-01-08 20:32:16 -06:00
|
|
|
};
|
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// Computes the length of the provided list.
|
2019-02-04 19:48:51 -06:00
|
|
|
let len = func(list) => reduce(func(acc, item) => acc + 1, 0, list);
|
2019-01-08 20:32:16 -06:00
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// Reverses the provided list.
|
2019-02-04 19:48:51 -06:00
|
|
|
let reverse = func(list) => reduce(func (acc, item) => [item] + acc, [], list);
|
2019-01-09 22:33:03 -06:00
|
|
|
|
2019-02-25 20:24:24 -06:00
|
|
|
// head returns the first item in a list as a list of one item.
|
|
|
|
// This function is safe for empty list inputs but is not safe
|
|
|
|
// for NULL inputs.
|
|
|
|
let head = func(list) => select len(list) > 0, [], {
|
|
|
|
true = [list.0],
|
|
|
|
};
|
|
|
|
|
|
|
|
// tail returns the tail of a list without the head.
|
|
|
|
// This function is safe for empty lists but is not safe
|
|
|
|
// for NULL inputs.
|
|
|
|
let tail = func(list) => reduce(
|
|
|
|
func (acc, item) => select acc.count > 0, acc{count=1, tail=[]}, {
|
|
|
|
true = acc{count = acc.count + 1, tail = acc.tail + [item]},
|
|
|
|
},
|
|
|
|
{count=0},
|
|
|
|
list,
|
|
|
|
).tail;
|
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// 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"]]
|
2019-01-08 20:32:16 -06:00
|
|
|
let enumerate = module{
|
2019-02-04 20:29:04 -06:00
|
|
|
// Where to start the enumeration.
|
2019-01-08 20:32:16 -06:00
|
|
|
start = 0,
|
2019-02-04 20:29:04 -06:00
|
|
|
// The step amount for each enumeration.
|
2019-01-08 20:32:16 -06:00
|
|
|
step = 1,
|
2019-02-04 20:29:04 -06:00
|
|
|
// The list to enumerate.
|
2019-01-08 20:32:16 -06:00
|
|
|
list = NULL,
|
2019-02-24 08:16:07 -06:00
|
|
|
} => (result) {
|
2019-01-24 20:04:40 -06:00
|
|
|
let reducer = func (acc, item) => acc{
|
2019-01-16 19:07:03 -06:00
|
|
|
count = acc.count + acc.step,
|
|
|
|
list=acc.list + [[acc.count, item]],
|
2019-01-08 20:32:16 -06:00
|
|
|
};
|
|
|
|
|
2019-02-18 20:15:54 -06:00
|
|
|
let result = reduce(
|
|
|
|
reducer,
|
|
|
|
{count=mod.start, list=[], step=mod.step},
|
|
|
|
(mod.list)).list;
|
2019-01-10 18:38:14 -06:00
|
|
|
};
|
|
|
|
|
2019-02-27 19:33:14 -06:00
|
|
|
// slice returns a slice of a list starting at index start up to and
|
|
|
|
// including index end, inclusive.
|
|
|
|
let slice = module {
|
|
|
|
start = 0,
|
|
|
|
end = NULL,
|
|
|
|
list = NULL,
|
|
|
|
} => (result) {
|
|
|
|
let list = import "std/lists.ucg";
|
|
|
|
|
|
|
|
let list_len = list.len(mod.list);
|
|
|
|
|
|
|
|
let end = select mod.end is "null", mod.end, {
|
|
|
|
true = list_len,
|
|
|
|
};
|
|
|
|
|
|
|
|
// ensure some invariants
|
|
|
|
(mod.start >= 0) || fail "Slice must be positive";
|
|
|
|
(mod.start <= list_len) || fail "Slice start cannot be larger than the list len of @" % (list_len);
|
|
|
|
(end <= list_len) || fail "Slice end cannot be larger than list len of @" % (list_len);
|
|
|
|
|
|
|
|
let reducer = func(acc, item) => acc{
|
|
|
|
count = acc.count + 1,
|
|
|
|
list = select (acc.count >= mod.start) && (acc.count <= end), acc.list, {
|
|
|
|
true = acc.list + [item],
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
let result = reduce(
|
|
|
|
reducer,
|
|
|
|
{count=mod.start, list=[]},
|
|
|
|
mod.list).list;
|
|
|
|
};
|
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// zips two lists together.
|
|
|
|
//
|
|
|
|
// zip{list1=[0,2,4],list2=[1,3,5]}.result == [[0, 1], [2, 3], [4, 5]]
|
2019-01-10 18:38:14 -06:00
|
|
|
let zip = module{
|
|
|
|
list1 = NULL,
|
|
|
|
list2 = NULL,
|
2019-02-24 08:16:07 -06:00
|
|
|
} => (result) {
|
2019-02-04 19:48:51 -06:00
|
|
|
let len = import "std/lists.ucg".len;
|
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// Compute the length of each list.
|
2019-02-04 19:48:51 -06:00
|
|
|
let len1 = len(mod.list1);
|
|
|
|
let len2 = len(mod.list2);
|
2019-01-10 18:38:14 -06:00
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// Compute the min range of the two lists.
|
2019-01-10 18:38:14 -06:00
|
|
|
let rng = select (len1 >= len2), NULL, {
|
|
|
|
true = 0:(len1 - 1),
|
|
|
|
false = 0:(len2 - 1),
|
|
|
|
};
|
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// The reducer function for the zip operation.
|
2019-01-24 20:04:40 -06:00
|
|
|
let reducer = func (acc, item) => acc{
|
2019-01-16 19:07:03 -06:00
|
|
|
result = acc.result + [[acc.list1.(item), acc.list2.(item)]],
|
|
|
|
idxs = acc.idxs + [item]
|
2019-01-10 18:38:14 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
let acc = {
|
|
|
|
list1 = mod.list1,
|
|
|
|
list2 = mod.list2,
|
|
|
|
result = [],
|
|
|
|
idxs = [],
|
|
|
|
};
|
|
|
|
|
2019-02-04 20:29:04 -06:00
|
|
|
// The resulting zipped list.
|
2019-01-31 16:33:12 -06:00
|
|
|
let result = reduce(reducer, acc, rng).result;
|
2019-01-08 20:32:16 -06:00
|
|
|
};
|