From ea3f2eae5f96aeb97e21899e6d2aadea35d9b6b6 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Wed, 27 Feb 2019 19:33:14 -0600 Subject: [PATCH] FEATURE: Add a slice module to our lists library. --- docsite/site/content/stdlib/lists.md | 13 +++++++++++ std/lists.ucg | 33 ++++++++++++++++++++++++++++ std/tests/lists_test.ucg | 25 +++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/docsite/site/content/stdlib/lists.md b/docsite/site/content/stdlib/lists.md index f4d0c41..d859fbe 100644 --- a/docsite/site/content/stdlib/lists.md +++ b/docsite/site/content/stdlib/lists.md @@ -63,6 +63,19 @@ let hd = l.head([0,1,2,3]); tail == [0]; ``` +## slice + +The slice module returns a slice of the input list. The slice module takes three +parameters. + +* `start` which is optional and defaults to 0 +* `end` which is optional and defaults the length of the list +* `list` which is required and must be a list. + +``` +list.slice{start=0, end=2, list=[0,1,2,3]} == [0,1,2]; +``` + ## enumerate The enumerate module enumerates the elements of a list. It has three parameters. diff --git a/std/lists.ucg b/std/lists.ucg index a58cd7c..95a2e2a 100644 --- a/std/lists.ucg +++ b/std/lists.ucg @@ -70,6 +70,39 @@ let enumerate = module{ (mod.list)).list; }; +// 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; +}; + // zips two lists together. // // zip{list1=[0,2,4],list2=[1,3,5]}.result == [[0, 1], [2, 3], [4, 5]] diff --git a/std/tests/lists_test.ucg b/std/tests/lists_test.ucg index 2339524..9b4eabb 100644 --- a/std/tests/lists_test.ucg +++ b/std/tests/lists_test.ucg @@ -52,4 +52,29 @@ assert asserts.equal{ assert asserts.equal{ left=list.head([0,1,2,3,4]), right=[0], +}; + +assert asserts.equal{ + left=list.slice{end=2, list=[0,1,2,3]}, + right=[0,1,2], +}; + +assert asserts.equal{ + left=list.slice{list=[0,1,2,3]}, + right=[0,1,2,3], +}; + +assert asserts.equal{ + left=list.slice{end=0, list=[0,1,2,3]}, + right=[0], +}; + +assert asserts.equal{ + left=list.slice{list=[]}, + right=[], +}; + +assert asserts.equal{ + left=list.slice{list=[0]}, + right=[0], }; \ No newline at end of file