Skip to content

Commit

Permalink
stdlib: Add list functions (#1648)
Browse files Browse the repository at this point in the history
* stdlib: Add list functions

* fix performance

* Add difference function

* address comments

* timing

* bonk
  • Loading branch information
V-FEXrt authored Sep 23, 2024
1 parent 9ffa855 commit 9205a3a
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 4 deletions.
89 changes: 89 additions & 0 deletions share/wake/lib/core/list.wake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion tests/inspection/canceled/stdout
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# (1)
$ sleep 10
$ sleep 1000
2 changes: 1 addition & 1 deletion tests/inspection/canceled/test.wake
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 19 additions & 1 deletion tests/standard-library/list/pass.sh
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions tests/standard-library/list/stdout
Original file line number Diff line number Diff line change
@@ -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
26 changes: 25 additions & 1 deletion tests/standard-library/list/test.wake
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 9205a3a

Please sign in to comment.