diff --git a/share/wake/lib/core/list.wake b/share/wake/lib/core/list.wake index 238f81467..e549a28b4 100644 --- a/share/wake/lib/core/list.wake +++ b/share/wake/lib/core/list.wake @@ -889,3 +889,92 @@ export def groupBy (cmpFn: a => a => Order) (list: List a): List (List a) = _ -> (elem, Nil), acc foldr combo Nil sorted + +# Returns a list of items where each item was a member of the two parameter lists. +# The returned list will not be the same order as the parameters. +# +# Guarantees: +# - Output list length will be <= the length of the smaller input list +# - All items in output list will be present in both input lists +# - Performance is considered and exceeds the naive N^2 algorithm +# +# Examples: +# ``` +# intersect icmp (seq 3) (seq 4) = 0, 1, 2, Nil +# intersect icmp (seq 3) (seq 3) = 0, 1, 2, Nil +# intersect icmp (seq 3) (4, 2, 0, Nil) = 0, 2, Nil +# intersect scmp ("", "bar", "bat", Nil) ("", "foo", "bat", Nil) = "", "bat", Nil +# ``` +export def intersect (cmpFn: a => a => Order) (left: List a) (right: List a): List a = + def intersectImp cmpFn leftSort rightSort = match leftSort rightSort + # If either list is exhuasted then no more matches are possible + Nil _ -> Nil + _ Nil -> Nil + (lh, lt) (rh, rt) -> match (cmpFn lh rh) + # lh is smaller so drop it + LT -> intersectImp cmpFn lt (rh, rt) + # rh is smaller so drop it + GT -> intersectImp cmpFn (lh, lt) rt + # equal, grab and continue + EQ -> lh, (intersectImp cmpFn lt rt) + + intersectImp cmpFn (sortBy cmpFn left) (sortBy cmpFn right) + +# Returns a Boolean determining if all items in left are also item in right. +# +# Guarantees: +# - True is returned only when all items of left are present in right +# - Performance is considered and exceeds the naive N^2 algorithm +# +# Examples: +# subset icmp (seq 3) (seq 4) = True +# subset icmp (seq 3) (seq 3) = True +# subset icmp (seq 3) (seq 2) = False +# subset icmp (seq 3) (4, 2, 0, Nil) = False +# subset icmp Nil Nil = True +# subset icmp Nil (seq 1) = True +# subset icmp (seq 1) Nil = False +# subset scmp ("", Nil) ("", "foo", "bar", Nil) = True +# subset scmp ("", "bat", Nil) ("", "foo", "bar", Nil) = False +export def subset (cmpFn: a => a => Order) (left: List a) (right: List a): Boolean = + def subsetImp cmpFn leftSort rightSort = match leftSort rightSort + Nil _ -> True + _ Nil -> False + (lh, lt) (rh, rt) -> match (cmpFn lh rh) + LT -> False + GT -> subsetImp cmpFn (lh, lt) rt + EQ -> subsetImp cmpFn lt rt + + subsetImp cmpFn (sortBy cmpFn left) (sortBy cmpFn right) + +# Remove all items from the left list which occur in the right. +# The returned list will not be the same order as the parameters. +# +# Guarantees: +# - Output list length will be <= the length of left +# - All items in output list will be present in left +# - No items in output list will be present in right +# - Performance is considered and exceeds the naive N^2 algorithm +# +# Examples: +# ``` +# subtract icmp (seq 4) (seq 3) = 3, Nil +# subtract icmp (seq 3) (seq 3) = Nil +# subtract icmp (seq 3) (2, Nil) = 0, 1, Nil +# subtract scmp ("", "bar", "bat", Nil) ("", "foo", "bat", Nil) = "bar", Nil +# ``` +export def subtract (cmpFn: a => a => Order) (left: List a) (right: List a): List a = + def subtractImp cmpFn leftSort rightSort = match leftSort rightSort + # left is empty so the result will always be empty + Nil _ -> Nil + # right is empty nothing else to subtract so result will always be left + l Nil -> l + (lh, lt) (rh, rt) -> match (cmpFn lh rh) + # lh is smaller, add it to the output set then continue looking in lt + LT -> lh, (subtractImp cmpFn lt (rh, rt)) + # rh is smaller so drop it, then continue looking in (lh, lt) + GT -> subtractImp cmpFn (lh, lt) rt + # item is in both sets. Remove it then continue looking + EQ -> subtractImp cmpFn lt rt + + subtractImp cmpFn (sortBy cmpFn left) (sortBy cmpFn right) diff --git a/tests/inspection/canceled/stdout b/tests/inspection/canceled/stdout index 61adfa2f4..e1befc066 100644 --- a/tests/inspection/canceled/stdout +++ b/tests/inspection/canceled/stdout @@ -1,2 +1,2 @@ # (1) -$ sleep 10 +$ sleep 1000 diff --git a/tests/inspection/canceled/test.wake b/tests/inspection/canceled/test.wake index b68148708..d53bcaa14 100644 --- a/tests/inspection/canceled/test.wake +++ b/tests/inspection/canceled/test.wake @@ -2,7 +2,7 @@ from wake import _ export def test _: Result Unit Error = def _ = - makeExecPlan ("sleep", "10",) Nil + makeExecPlan ("sleep", "1000",) Nil | runJobWith defaultRunner Pass Unit diff --git a/tests/standard-library/list/pass.sh b/tests/standard-library/list/pass.sh index 94c64b882..5d894cfe3 100755 --- a/tests/standard-library/list/pass.sh +++ b/tests/standard-library/list/pass.sh @@ -1,4 +1,22 @@ #! /bin/sh WAKE="${1:+$1/wake}" -"${WAKE:-wake}" --stdout=warning,report test + +"${WAKE:-wake}" --stdout=warning,report test1 +"${WAKE:-wake}" --stdout=warning,report test2 +"${WAKE:-wake}" --stdout=warning,report test3 +"${WAKE:-wake}" --stdout=warning,report test4 +"${WAKE:-wake}" --stdout=warning,report test5 +"${WAKE:-wake}" --stdout=warning,report test6 +"${WAKE:-wake}" --stdout=warning,report test7 +"${WAKE:-wake}" --stdout=warning,report test8 +"${WAKE:-wake}" --stdout=warning,report test9 +"${WAKE:-wake}" --stdout=warning,report test10 +"${WAKE:-wake}" --stdout=warning,report test11 +"${WAKE:-wake}" --stdout=warning,report test12 +"${WAKE:-wake}" --stdout=warning,report test13 +"${WAKE:-wake}" --stdout=warning,report test14 +"${WAKE:-wake}" --stdout=warning,report test15 +"${WAKE:-wake}" --stdout=warning,report test16 +"${WAKE:-wake}" --stdout=warning,report test17 +"${WAKE:-wake}" --stdout=warning,report test18 diff --git a/tests/standard-library/list/stdout b/tests/standard-library/list/stdout index 9f7ca79cf..a32891a2d 100644 --- a/tests/standard-library/list/stdout +++ b/tests/standard-library/list/stdout @@ -1 +1,18 @@ (0, 1, 2, Nil), (3, 4, 5, Nil), (6, 7, 8, Nil), (9, 10, Nil), Nil +0, 1, 2, Nil +0, 1, 2, Nil +0, 2, Nil +"", "bat", Nil +True +True +False +False +True +True +False +True +False +3, Nil +Nil +0, 1, Nil +"bar", Nil diff --git a/tests/standard-library/list/test.wake b/tests/standard-library/list/test.wake index 74ba05b90..af7401191 100644 --- a/tests/standard-library/list/test.wake +++ b/tests/standard-library/list/test.wake @@ -1 +1,25 @@ -export def test _ = seq 11 | groupBy (\l\r icmp (l/3) (r/3)) +# groupBy tests +export def test1 _ = seq 11 | groupBy (\l\r icmp (l/3) (r/3)) + +# intersect tests +export def test2 _ = intersect icmp (seq 3) (seq 4) +export def test3 _ = intersect icmp (seq 3) (seq 3) +export def test4 _ = intersect icmp (seq 3) (4, 2, 0, Nil) +export def test5 _ = intersect scmp ("", "bar", "bat", Nil) ("", "foo", "bat", Nil) + +# subset tests +export def test6 _ = subset icmp (seq 3) (seq 4) +export def test7 _ = subset icmp (seq 3) (seq 3) +export def test8 _ = subset icmp (seq 3) (seq 2) +export def test9 _ = subset icmp (seq 3) (4, 2, 0, Nil) +export def test10 _ = subset icmp Nil Nil +export def test11 _ = subset icmp Nil (seq 1) +export def test12 _ = subset icmp (seq 1) Nil +export def test13 _ = subset scmp ("", Nil) ("", "foo", "bar", Nil) +export def test14 _ = subset scmp ("", "bat", Nil) ("", "foo", "bar", Nil) + +# subtract tests +export def test15 _ = subtract icmp (seq 4) (seq 3) +export def test16 _ = subtract icmp (seq 3) (seq 3) +export def test17 _ = subtract icmp (seq 3) (2, Nil) +export def test18 _ = subtract scmp ("", "bar", "bat", Nil) ("", "foo", "bat", Nil)