summaryrefslogtreecommitdiff
path: root/desk/lib/seq.hoon
diff options
context:
space:
mode:
Diffstat (limited to 'desk/lib/seq.hoon')
-rw-r--r--desk/lib/seq.hoon1809
1 files changed, 1809 insertions, 0 deletions
diff --git a/desk/lib/seq.hoon b/desk/lib/seq.hoon
new file mode 100644
index 0000000..12f8d26
--- /dev/null
+++ b/desk/lib/seq.hoon
@@ -0,0 +1,1809 @@
+:: /lib/seq/hoon
+:: |seq
+:: operations for working with values of type list
+::
+|%
+:: +all-pairs: [(list T1) (list T2)] -> (list [T1 T2])
+::
+:: Returns a new list that contains all pairings of elements from two non-empty
+:: lists.
+:: Examples
+:: > (all-pairs ~['a' 'b' 'c'] ~[1 2 3])
+:: ~[['c' 3] ['c' 2] ['c' 1]
+:: ['b' 3] ['b' 2] ['b' 1]
+:: ['a' 3] ['a' 2] ['a' 1]]
+:: Source
+++ all-pairs
+ |* [p=(list) q=(list)]
+ =/ a=(list _?>(?=(^ p) i.p)) p
+ =/ res=(list [_?>(?=(^ p) i.p) _?>(?=(^ q) i.q)]) ~
+ =/ scnd=(list _?>(?=(^ q) i.q)) q
+ |- ^- (list [_?>(?=(^ p) i.p) _?>(?=(^ q) i.q)])
+ ?~ a res
+ ?~ scnd $(a t.a, scnd q)
+ $(res [[i.a i.scnd] res], scnd +.scnd)
+:: +append: [(list) (list)] -> (list)
+::
+:: Returns a new list that contains the elements of the first list followed by
+:: elements of the second list.
+:: Examples
+:: > (append "urb" "it")
+:: "urbit"
+:: > (append (limo [1 2 ~]) (limo [3 4 ~]))
+:: ~[1 2 3 4]
+:: Source
+++ append weld
+:: +average: (list @) -> @ud
+::
+:: Returns the average of the values in a non-empty list.
+:: Examples
+:: > (average `(list @ud)`~[1 2 3 4])
+:: 2
+:: Source
+++ average
+ |* a=(list @)
+ (div (roll a add) (lent a))
+:: +average-by: [(list T) projection:$-(T @ud)] -> @ud
+::
+:: Returns the average of values in a list generated by applying a function to
+:: each element of the list.
+:: Examples
+:: > (average-by (limo ~[[1 1] [2 2] [3 3] [4 4]]) |=([a=@ b=@] (add a b)))
+:: 5
+:: Source
+++ average-by
+ |* [a=(list) b=$-(* @ud)]
+ (div (roll (turn a b) add) (lent a))
+:: +choose: [(list T1) $-(T1 (unit T2))] -> (list T2)
+::
+:: Applies a function to each element in a list and then returns a list of
+:: values v where the applied function returns (unit v).
+:: Returns an empty list when the input list is empty or when the applied
+:: chooser function returns ~ for all elements.
+:: Examples
+:: > =a |=(a=@ ?.((gte a 2) ~ (some (add a 10))))
+:: > (choose `(list @)`[0 1 2 3 ~] a)
+:: [i=12 t=[i=13 t=~]]
+:: Source
+++ choose murn
+:: +chunk-by-size: [(list T) chunkSize:@] -> (list (list T))
+::
+:: Divides the input list into lists (chunks) with a positive number of at
+:: most chunkSize elements. Returns a new list containing the generated lists
+:: (chunks) as its elements. Returns an empty list when the input list is empty
+:: Examples
+:: > (chunk-by-size (limo ~[1 2 3 4 5 6 7]) 2)
+:: [i=~[1 2] t=[i=~[3 4] t=~[~[5 6] ~[7]]]]
+:: Crash
+:: 'chunk size is 0'
+:: Source
+++ chunk-by-size
+ |* [p=(list) q=@ud]
+ ?: =(0 q) ~|('chunk size is 0' !!)
+ =/ res=(list (list _?>(?=(^ p) i.p))) ~
+ =/ i=@ud 0
+ =/ next=(list _?>(?=(^ p) i.p)) ~
+ |- ^- (list (list _?>(?=(^ p) i.p)))
+ ?~ p (flop [(flop next) res])
+ ?: =(i q) $(i 0, res [(flop next) res], next ~)
+ $(i +(i), next [i.p next], p t.p)
+:: +collect: [(list T1) mapping:$-(T1 (list T2))] -> (list T2)
+::
+:: For each element of the list, applies the given function. Concatenates all
+:: the results and return the combined list.
+:: Examples
+:: > (collect (limo ~[1 2 3]) |=(a=* (limo ~[a a])))
+:: ~[1 1 2 2 3 3]
+:: Source
+++ collect
+ |* [p=(list) q=$-(* (list))]
+ =/ res=(list) ~
+ |-
+ ?~ p (flop res)
+ =/ c=(list) (q i.p)
+ |-
+ ?~ c ^$(p t.p)
+ $(c t.c, res [i.c res])
+:: +compare: [(list T) (list T) comparer:$-([T T] ?)] -> (list ?)
+::
+:: Compares two lists element by element using the given comparison function.
+:: When an entry exists for both lists, returns the result of the comparer
+:: function. When the second list is longer than the first returns %.y for
+:: entries of second where first does not exist. When first list is longer
+:: returns %.n for entries of first where second does not exist.
+:: Examples
+:: > (compare "when" "than" aor)
+:: ~[%.n %.y %.n %.y]
+:: Source
+++ compare
+ |* [b=(list) c=(list) a=$-([* *] ?)]
+ =/ res=(list ?) ~
+ =/ bb b
+ =/ cc c
+ |- ^- (list ?)
+ ?~ bb ?~ cc (flop res) $(cc t.cc, res [%.y res])
+ ?~ cc $(bb t.bb, res [%.n res])
+ $(bb t.bb, cc t.cc, res [(a i.bb i.cc) res])
+:: +concat: (list (list)) -> (list)
+::
+:: Returns a new list that contains the elements of each of the lists in order.
+:: Examples
+:: > (concat (limo [(limo ['a' 'b' 'c' ~]) (limo ['e' 'f' 'g' ~])
+:: (limo ['h' 'i' 'j' ~]) ~]))
+:: ~['a' 'b' 'c' 'e' 'f' 'g' 'h' 'i' 'j']
+:: > (concat (limo [(limo [1 'a' 2 'b' ~]) (limo [3 'c' 4 'd' ~]) ~]))
+:: ~[1 97 2 98 3 99 4 100]
+:: Source
+++ concat zing
+:: +contains: [(list) value:*] -> ?
+::
+:: Tests if the list contains the specified element.
+:: Examples
+:: > (contains "yep" `(list tape)`~["nope" "yep"])
+:: %.y
+:: Source
+++ contains
+ |* [p=(list) q=*]
+ |- ^- ?
+ ?~ p %.n
+ ?: =(q i.p) %.y
+ $(p t.p)
+:: +count-by: [(list T1) projection:$-(T1 T2)] -> (list [T2 @ud])
+::
+:: Applies a key-generating function to each element of a list and returns a
+:: list yielding unique keys and their number of occurrences in the original
+:: list.
+:: Examples
+:: > %: count-by
+:: (limo ~["where" "when" "there" "then"])
+:: |=(a=tape (scag 2 a))
+:: ==
+:: ~[[[i=t' t="h"] 2] [[i='w' t="h"] 2]]
+:: Source
+++ count-by
+ |* [p=(list) q=$-(* *)]
+ =/ res=(map _?>(?=(^ p) (q i.p)) @ud) ~
+ |- ^- (list [_?>(?=(^ p) (q i.p)) @ud])
+ ?~ p ~(tap by res)
+ =/ key=_?>(?=(^ p) (q i.p)) (q i.p)
+ =/ val (~(get by res) key)
+ ?~ val $(res `(map _?>(?=(^ p) (q i.p)) @ud)`(~(put by res) key 1), p t.p)
+ %= $
+ res `(map _?>(?=(^ p) (q i.p)) @ud)`(~(put by res) key +(`@ud`(need val)))
+ p t.p
+ ==
+:: +distinct: (list) -> (list)
+::
+:: Returns a list that contains no duplicate entries according to generic hash
+:: and equality comparisons on the entries. If an element occurs multiple times
+:: in the list then the later occurrences are discarded.
+:: Examples
+:: > (distinct `(list tape)`~["tape1" "tape0" "tape1" "tape0"])
+:: ~["tape1" "tape0"]
+:: Source
+++ distinct
+ |* a=(list)
+ =/ b=(list _?>(?=(^ a) i.a)) ~
+ =/ c=(set) ~
+ |- ^+ a
+ ?~ a (flop b)
+ ?: (~(has in c) i.a) $(a t.a)
+ $(a t.a, b [i.a b], c (~(put in c) i.a))
+:: +distinct-by: [(list T1) projection:$-(T1 T2)] -> (list T1)
+::
+:: Returns a list that contains no duplicate entries according to the generic
+:: hash and equality comparisons on the keys returned by the given
+:: key-generating function. If an element occurs multiple times in the list
+:: then the later occurrences are discarded.
+:: Examples
+:: > =foo `(list [@ @])`~[[1 1] [1 2] [1 3] [2 1]]
+:: > (distinct-by foo |=([a=@ b=@] (add a b)))
+:: ~[[1 1] [1 2] [1 3]]
+:: Source
+++ distinct-by
+ |* [p=(list) q=$-(* *)]
+ =/ b=(list _?>(?=(^ p) i.p)) ~
+ =/ c=(set) ~
+ |- ^+ p
+ ?~ p (flop b)
+ ?: (~(has in c) (q i.p)) $(p t.p)
+ $(p t.p, b [i.p b], c (~(put in c) (q i.p)))
+:: +empty: $ -> *(list $)
+::
+:: Returns an empty list typed by the mold. (The bunt of the typed list.)
+:: Examples
+:: > (empty @t)
+:: ~
+:: Source
+++ empty
+ |* a=mold
+ *(list a)
+:: +exactly-one: (list T) -> T
+::
+:: Returns the only element of the list. Crashes if list has different length.
+:: Examples
+:: > (exactly-one (limo ~["tape"]))
+:: "tape"
+:: Crash
+:: 'list length is not 1'
+:: Source
+++ exactly-one
+ |* a=(list)
+ ?: =(1 (lent a)) -.a
+ ~|('list length is not 1' !!)
+:: +except: [(list T) items-to-exclude:(list T)] -> (list T)
+::
+:: Returns a new list with the distinct elements of the input list which do not
+:: appear in the items-to-exclude list, using generic hash and equality
+:: comparisons to compare values.
+:: Examples
+:: > %: except
+:: (limo ~["able" "baker" "charlie" "dog"])
+:: (limo ~["baker" "dog"])
+:: ==
+:: ~[[i='a' t="ble"] [i='c' t="harlie"]]
+:: Source
+++ except
+ |* [p=(list) q=(list)]
+ =/ qq (silt q)
+ =/ b=(list _?>(?=(^ p) i.p)) ~
+ |- ^+ p
+ ?~ p (flop b)
+ ?: (~(has in qq) i.p) $(p t.p)
+ $(p t.p, b [i.p b], qq (~(put in qq) i.p))
+:: +exists: [(list T) predicate:$-(T ?)] -> ?
+::
+:: Tests if any element of the list satisfies the given predicate.
+:: Examples
+:: > =foo |= a=tape
+:: ?: ?&(=(4 (lent a)) =('a' -.a)) %.y %.n
+:: > (exists (limo ~["aaa" "able" "baker" "charlie" "dog"]) foo)
+:: %.y
+:: Source
+++ exists
+ |* [a=(list) b=$-(* ?)]
+ |- ^- ?
+ ?~ a %.n
+ ?: (b i.a) %.y
+ $(a t.a)
+:: +exists2: [(list T1) (list T2) predicate:$-([T1 T2] ?)] -> ?
+::
+:: Tests if any pair of corresponding elements of the lists satisfies the given
+:: predicate.
+:: Examples
+:: > =foo |= [a=tape b=tape]
+:: ?: =(-.a -.b) %.y %.n
+:: > (exists2 (limo ~["cat" "betty"]) (limo ~["able" "butter"]) foo)
+:: %.y
+:: Source
+++ exists2
+ |* [a=(list) b=(list) c=$-([* *] ?)]
+ |- ^- ?
+ ?~ a %.n
+ ?~ b %.n
+ ?: (c [i.a i.b]) %.y
+ $(a t.a, b t.b)
+:: +filter: [(list T) predicate:$-(T ?)] -> (list T)
+::
+:: Returns a new list containing only the elements of the list for
+:: which the given predicate returns "true"
+:: Examples
+:: > =a |=(a=@ (gth a 1))
+:: > (filter `(list @)`[0 1 2 3 ~] a)
+:: [i=2 t=~[3]]
+:: Source
+++ filter skim
+::
+:: +findx: [(list T) predicate:$-(T ?)] -> T
+::
+:: Returns the first element for which the given function returns True.
+:: Crashes if no such element exists.
+:: Examples
+:: > (findx (gulf [1 30]) |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5)))))
+:: 15
+:: Crash
+:: 'not found'
+:: Source
+++ findx
+ |* [a=(list) b=$-(* ?)]
+ |- ^- _?>(?=(^ a) i.a)
+ ?~ a ~|('not found' !!)
+ ?: (b i.a) i.a $(a t.a)
+:: +find-all: [(list T) predicate:$-(T ?)] -> (list T))
+::
+:: Returns all elements for which the given function returns True.
+:: Crashes if no such element exists.
+:: Examples
+:: > (find-all (gulf [1 30]) |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5)))))
+:: ~[15 30]
+:: Crash
+:: 'not found'
+:: Source
+++ find-all
+ |* [a=(list) b=$-(* ?)]
+ =/ c=(list _?>(?=(^ a) i.a)) ~
+ |-
+ ?~ a ?~ c ~|('not found' !!) (flop c)
+ ?: (b i.a) $(a t.a, c [i.a c]) $(a t.a)
+:: +find-all-by-list: [(list T) arg:(list T) -> (list @)]
+::
+:: Produces list of indices of all occurrences of the argument list sequence in
+:: the sequence of the source list.
+:: Examples
+:: > (find-all-by-list "cbabab" "ba")
+:: ~[1 3]
+:: Source
+++ find-all-by-list
+ |* [hstk=(list) nedl=(list)]
+ ^- (list @)
+ (fand nedl hstk)
+:: +find-all-by-unit: [(list T1) chooser:$-(T1 (unit T2))] -> (list T2)
+::
+:: Applies the given function to successive elements, returning the list of
+:: elements where the function returns Some(x).
+:: Crashes when no such element exists.
+:: Examples
+:: > %: find-all-by-unit
+:: (limo ~[1 2 3 4])
+:: |=(a=@ ?:(=((mod a 2) 0) `a ~))
+:: ==
+:: ~[2 4]
+:: Crash
+:: 'not found'
+:: Source
+++ find-all-by-unit
+ |* [hstk=(list) nedl=$-(* (unit *))]
+ =/ b=(list _?>(?=(^ hstk) i.hstk)) ~
+ |- ^- (list _?>(?=(^ hstk) i.hstk))
+ ?~ hstk ?~ b ~|('not found' !!)
+ (flop b)
+ =/ x (nedl i.hstk)
+ ?~ x $(hstk t.hstk)
+ $(hstk t.hstk, b [(need x) b])
+:: +find-back: [(list T) predicate:$-(T ?)] -> T
+::
+:: Returns the last element for which the given function returns True.
+:: Crashes if no such element exists.
+:: Examples
+:: > %: find-back
+:: (gulf [1 30])
+:: |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5))))
+:: ==
+:: 30
+:: Crash
+:: 'not found'
+:: Source
+++ find-back
+ |* [a=(list) b=$-(* ?)]
+ ?~ a ~|('not found' !!)
+ (findx (flop a) b)
+:: +find-back-by-list: [(list T) arg:(list T)] -> @
+::
+:: Produces the index of the last occurrence of the argument list sequence in
+:: the sequence of the source list.
+:: Examples
+:: > (find-back-by-list "cbabab" "ba")
+:: 3
+:: Source
+++ find-back-by-list
+ |* [hstk=(list) nedl=(list)]
+ (tail-end (find-all-by-list hstk nedl))
+:: +find-back-by-unit: [(list T1) chooser:$-(T1 (unit T2))] -> T2
+::
+:: Applies the given function to successive elements from the end back,
+:: returning the first result where function returns Some(x) for some x.
+:: Crashes when no such element exists.
+:: Examples
+:: > %: find-back-by-unit
+:: (limo ~[1 2 3 4])
+:: |=(a=@ ?:(=((mod a 2) 0) `a ~))
+:: ==
+:: 4
+:: Crash
+:: 'not found'
+:: Source
+++ find-back-by-unit
+ |* [hstk=(list) nedl=$-(* (unit *))]
+ ^- _?>(?=(^ hstk) i.hstk)
+ (find-by-unit (flop hstk) nedl)
+:: +find-by-list: [(list T) arg:(list T)] -> @
+::
+:: Produces the index of the first occurrence of the argument list sequence in
+:: the sequence of the source list.
+:: Examples
+:: > (find-by-list "cbabab" "ab")
+:: 2
+:: Crash
+:: 'not found'
+:: Source
+++ find-by-list
+ |* [hstk=(list) nedl=(list)]
+ ^- @
+ =/ x (find nedl hstk)
+ ?~ x ~|('not found' !!) (need x)
+:: +find-by-unit: [(list T1) chooser:$-(T1 (unit T2))] -> T2
+::
+:: Applies the given function to successive elements, returning the first
+:: result where function returns Some(x) for some x. Crashes when no such
+:: element exists.
+:: Examples
+:: > (find-by-unit (limo ~[1 2 3 4]) |=(a=@ ?:(=((mod a 2) 0) `a ~)))
+:: 2
+:: Crash
+:: 'not found'
+:: Source
+++ find-by-unit
+ |* [hstk=(list) nedl=$-(* (unit *))]
+ |- ^- _?>(?=(^ hstk) i.hstk)
+ ?~ hstk ~|('not found' !!)
+ =/ x (nedl i.hstk)
+ ?~ x $(hstk t.hstk)
+ (need x)
+:: +find-index: [(list T) predicate:$-(T ?)] -> @
+::
+:: Returns the index of the first element in the list that satisfies the given
+:: predicate. Crashes if no such element exists.
+:: Examples
+:: > %: find-index
+:: (gulf [1 30])
+:: |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5))))
+:: ==
+:: 14
+:: Crash
+:: 'not found'
+:: Source
+++ find-index
+ |* [a=(list) b=$-(* ?)]
+ =/ i 0
+ |- ^- @
+ ?~ a ~|('not found' !!)
+ ?: (b i.a) i $(a t.a, i +(i))
+:: +find-index-all: [(list T) predicate:$-(T ?)] -> (list @)
+::
+:: Returns the list of indices in the list that satisfies the given predicate.
+:: Examples
+:: > %: find-index-all
+:: (gulf [1 30])
+:: |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5))))
+:: ==
+:: ~[14 29]
+:: Source
+++ find-index-all
+ |* [a=(list) b=$-(* ?)]
+ =/ c=(list @) ~
+ =/ i 0
+ |- ^- (list @)
+ ?~ a (flop c)
+ ?: (b i.a) $(a t.a, c [i c], i +(i)) $(a t.a, i +(i))
+:: +find-index-back: [(list T) predicate:$-(T ?)] -> @
+::
+:: Returns the index of the last element in the list that satisfies the given
+:: predicate. Crashes if no such element exists.
+:: Examples
+:: > %: find-index-back
+:: (gulf [1 30])
+:: |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5))))
+:: ==
+:: 29
+:: Crash
+:: 'not found'
+:: Source
+++ find-index-back
+ |* [a=(list) c=$-(* ?)]
+ ?~ a ~|('not found' !!)
+ =/ b (flop a)
+ =/ i (dec (lent a))
+ |- ^- @ud
+ ?~ b ~|('not found' !!)
+ ?: (c i.b) i
+ ?: =(0 i) ~|('not found' !!)
+ $(b t.b, i (dec i))
+:: +first-n: [(list T) count:@ud] -> (list T)
+::
+:: Returns the first N elements of the list.
+:: Examples
+:: > (first-n `(list @)`[1 2 3 4 ~] 2)
+:: [i=1 t=~[2]]
+:: > (first-n `(list @)`[1 2 3 4 ~] 10)
+:: [i=1 t=~[2 3 4]]
+:: Source
+++ first-n
+ |* [p=(list) q=@]
+ (scag q p)
+:: +fold: [(list T1) state:T2 folder:$-([T1 T2] T2)] -> T2
+::
+:: Applies a function to each element of the list, threading an
+:: accumulator argument through the computation. Take the second argument, and
+:: apply the function to it and the first element of the list. Then feed this
+:: result into the function along with the second element and so on. Return the
+:: final result. If the input function is f and the elements are i0...iN then
+:: computes f (... (f s i0) i1 ...) iN.
+:: Examples
+:: > (fold (gulf 1 5) 0 |=([n=@ state=@] (add state (mul n n))))
+:: 55
+:: Source
+++ fold
+ |* [a=(list) b=* c=_|=(^ [** +<+])]
+ |- ^- _b
+ ?~ a b
+ $(a t.a, b (c i.a b))
+:: +fold2: [(list T1) (list T2) state:T3 folder:$-([T1 T2 T3] T3)] -> T3
+::
+:: Applies a function to corresponding elements of two lists, threading
+:: an accumulator argument through the computation. The lists must have
+:: identical sizes. If the input function is f and the elements are i0...iN and
+:: j0...jN then computes f (... (f s i0 j0)...) iN jN.
+:: Examples
+:: > %: fold2
+:: (limo ~["Tails" "Head" "Tails"])
+:: (limo ~["Tails" "Head" "Head"])
+:: 0
+:: |=([n1=tape n2=tape state=@] ?:(=(n1 n2) +(state) state))
+:: ==
+:: 2
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ fold2
+ |* [a=(list) b=(list) c=* d=_|=(^ [** ** +<+])]
+ |- ^- _c
+ ?~ a ?~ b c ~|('lists of unequal length' !!)
+ ?~ b ~|('lists of unequal length' !!)
+ $(a t.a, b t.b, c (d i.a i.b c))
+:: +fold-back: [(list T1) state:T2 folder:$-([T1 T2] T2)] -> T2
+::
+:: Applies a function to each element of the list, starting from the end,
+:: threading an accumulator argument through the computation. If the input
+:: function is f and the elements are i0...iN then computes f i0 (...(f iN s)).
+:: Examples
+:: > =less-hungry |= [n=tape state=(list [tape @])]
+:: ^+ state
+:: ?~ state (limo ~[[n 1]])
+:: [[n +(+.i.state)] state]
+:: > %: fold-back
+:: (limo ~["Apple" "Pear" "Orange"])
+:: `(list [tape @])`~
+:: less-hungry
+:: ==
+:: [i=["Apple" 3] t=~[["Pear" 2] ["Orange" 1]]]
+:: Source
+++ fold-back
+ |* [a=(list) b=* c=$-([* *] *)]
+ (fold (flop a) b c)
+:: +fold-back2: [(list T1) (list T2) state:T3 folder:$-([T1 T2 T3] T3)] -> T3
+::
+:: Applies a function to corresponding elements of two lists, threading
+:: an accumulator argument through the computation. The lists must have
+:: identical sizes. If the input function is f and the elements are i0...iN and
+:: j0...jN then computes f i0 j0 (...(f iN jN s)).
+:: Examples
+:: > %: fold-back2
+:: (limo ~["Tails" "Head" "Tails"])
+:: (limo ~["Tails" "Head" "Head"])
+:: `(list tape)`~
+:: |=([n1=tape n2=tape state=(list tape)] [(weld n1 n2) state])
+:: ==
+:: ~["TailsTails" "HeadHead" "TailsHead"]
+:: Source
+++ fold-back2
+ |* [a=(list) b=(list) c=* d=$-([* * *] *)]
+ (fold2 (flop a) (flop b) c d)
+:: +forall: [(list T) predicate:$-(T ?)] -> ?
+::
+:: Tests if all elements of the list satisfy the given predicate.
+:: Examples
+:: > (forall (limo ~[2 4 8]) |=(a=@ ?:(=(0 (mod a 2)) %.y %.n)))
+:: %.y
+:: > (forall (limo ~[2 1 8]) |=(a=@ ?:(=(0 (mod a 2)) %.y %.n)))
+:: %.n
+:: Source
+++ forall
+ |* [a=(list) predicate=$-(* ?)]
+ |- ^- ?
+ ?~ a %.y
+ ?. (predicate i.a) %.n
+ $(a t.a)
+:: +forall2: [(list T1) (list T2) predicate:$-([T1 T2] ?)] -> ?
+::
+:: Tests if all corresponding elements of the list satisfy the given
+:: predicate pairwise. Crashes on lists of unequal length
+:: Examples
+:: > %: forall2
+:: (limo ~[1 4 8])
+:: (limo ~[3 4 8])
+:: |=([a=@ b=@] ?:(=(0 (mod (add a b) 2)) %.y %.n))
+:: ==
+:: %.y
+:: > %: forall2
+:: (limo ~[1 5 8])
+:: (limo ~[3 4 8])
+:: |=([a=@ b=@] ?:(=(0 (mod (add a b) 2)) %.y %.n))
+:: ==
+:: %.n
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ forall2
+ |* [a=(list) b=(list) predicate=$-(* ?)]
+ ?. =((lent a) (lent b)) ~|('lists of unequal length' !!)
+ |- ^- ?
+ ?~ a %.y
+ ?~ b ~|('cant get here' !!)
+ ?. (predicate i.a i.b) %.n
+ $(a t.a, b t.b)
+:: +from-map: (map) -> (list [* *])
+::
+:: Produces the list of all key element pairs in map.
+:: Examples
+:: > =map-00 (to-map (limo ~[['aa' 1] ['bb' 2] ['cc' 3] ['dd' 4]]))
+:: > (from-map map-00)
+:: ~[[p='bb' q=2] [p='dd' q=4] [p='cc' q=3] [p='aa' q=1]]
+:: Source
+++ from-map
+ |* a=(map)
+ ~(tap by a)
+:: +from-set: -> (list)
+::
+:: Produces the list of element in set
+:: Examples
+:: > (from-set `(set tap)`[[n="tlon"] l=["urbit" ~ ~] r=["uqbar" ~ ~]])
+:: Source
+++ from-set
+ |* a=(set)
+ ~(tap in a)
+:: +get-head: (list T) -> T
+::
+:: Returns the first element of the list. Crashes on empty list.
+:: Examples
+:: > (get-head ~[1 2])
+:: 1
+:: Crash
+:: 'empty list'
+:: Source
+++ get-head
+ |* a=(list)
+ ?~ a ~|('empty list' !!)
+ i.a
+:: +get-tail: (list T) -> (list T)
+::
+:: Returns the list after removing the first element.
+:: Examples
+:: > (get-tail ~[1 2])
+:: ~[2]
+:: Crash
+:: 'empty list'
+:: Source
+++ get-tail
+ |* a=(list)
+ ?~ a ~|('empty list' !!)
+ t.a
+:: +group-by: [(list T1) projection:$-(T1 T2)] -> (list [T2 (list T1)])
+::
+:: Applies a key-generating function to each element of a list and yields a
+:: list of unique keys. Each unique key contains a list of all elements that
+:: match to this key.
+:: Examples
+:: > (group-by (gulf 1 5) |=(a=@ (mod a 2)))
+:: ~[[p=0 q=[i=4 t=~[[2 0]]]] [p=1 q=[i=5 t=~[[3 [1 0] 0]]]]]
+:: Source
+++ group-by
+ |* [a=(list) b=$-(* *)]
+ =/ d=(map * (list *)) ~
+ |-
+ ?~ a ~(tap by d)
+ =/ e (b i.a)
+ =/ f (~(get by d) e)
+ ?~ f $(a t.a, d (~(put by d) e ~[i.a]))
+ $(a t.a, d (~(put by d) e ~[i.a (need f)]))
+:: +indexed: (list T) -> (list [@ T])
+::
+:: Returns a new list whose elements are the corresponding elements of the
+:: input list paired with the index (from 0) of each element.
+:: Examples
+:: > (indexed (gulf 1 3))
+:: ~[[0 1] [1 2] [2 3]]
+:: Source
+++ indexed
+ |* a=(list)
+ =/ b=(list [@ _?>(?=(^ a) i.a)]) ~
+ =/ i 0
+ |- ^- (list [@ _?>(?=(^ a) i.a)])
+ ?~ a (flop b)
+ $(a t.a, b [[i i.a] b], i +(i))
+:: +init: [length:@ud initializer:$-(@ud T)] -> (list T)
+::
+:: Creates a list by calling the given generator on each index.
+:: Crashes on length = 0.
+:: Examples
+:: > (init 3 |=(a=@ (add a 5)))
+:: ~[6 7 8]
+:: Crash
+:: 'empty list'
+:: Source
+++ init
+ |* [len=@ ini=$-(@ *)]
+ =/ a=(list *) ~
+ ?: =(0 len) ~|('empty list' !!)
+ |-
+ ?: =(0 len) a
+ $(len (dec len), a [(ini len) a])
+:: +insert-at: [(list T) index:@ value:T] -> (list T)
+::
+:: Return a new list with a new item inserted before the given index.
+:: Examples
+:: > (insert-at (limo ~[2 3 4]) 1 11)
+:: ~[2 11 3 4]
+:: Source
+++ insert-at into
+:: +insertManyAt: [(list T) values=(list T) index=@] -> (list T)
+::
+:: Return a new list with new items inserted before the given index.
+:: Examples
+:: > (insert-many-at (limo ~[1 2 5 6 7]) (limo ~[3 4]) 2)
+:: ~[1 2 3 4 5 6 7]
+:: Crash
+:: 'out of range'
+:: Source
+++ insert-many-at
+ |* [a=(list) values=(list) i=@]
+ ?: =(0 (lent values)) a
+ =/ len-a (lent a)
+ ?: (gth i len-a) ~|('out of range' !!)
+ ?~ values a
+ ?: =(0 i) (weld values a)
+ ?: =(len-a i) (weld a values)
+ =/ start (scag i a)
+ =/ end (slag i a)
+ (weld (weld start values) end)
+:: +is-empty: (list) -> ?
+::
+:: Returns true if the list contains no elements, false otherwise.
+:: Examples
+:: > (is-empty `(list @)`~[2])
+:: %.n
+:: > (is-empty `(list @)`~)
+:: %.y
+:: Source
+++ is-empty
+ |* a=(list)
+ ?~ a %.y %.n
+:: +item: [(list T) index:@] -> T
+::
+:: Indexes into the list. The first element has index 0.
+:: Examples
+:: > (item `(list @)`~["aa" "bb" "cc" "dd"] 2)
+:: "cc"
+:: Source
+++ item
+ |* [a=(list) i=@]
+ (snag i a)
+:: +iter: [(list T) fun:$-(T *)] -> ~
+::
+:: Applies the given function to each element of the list, dropping the
+:: results.
+:: Examples
+:: > (iter (limo ~["tape1" "tape2"]) |=(a=tape (lent a)))
+:: ~
+:: Source
+++ iter
+ |* [a=(list) fun=$-(* *)]
+ =/ b (turn a fun)
+ ~
+:: +iter2: [(list T1) (list T2) fun:$-(T1 T2 *)] -> ~
+::
+:: Applies the given function to two lists simultaneously, dropping the
+:: results. The lists must have identical size.
+:: Examples
+:: > %: iter2
+:: (limo ~["tape1" "tape2"])
+:: (limo ~["tape3" "tape4"])
+:: |=([a=tape b=tape] (add (lent a) (lent b)))
+:: ==
+:: ~
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ iter2
+ |* [a=(list) b=(list) fun=$-(* *)]
+ =/ b (map2 a b fun)
+ ~
+:: +iteri: [(list T) fun:$-([@ T] *)] -> ~
+::
+:: Applies the given function to each element of the list and the index
+:: of element, dropping the results.
+:: Examples
+:: > (iteri (limo ~[1 2 3]) |=([a=@ b=@] (add a b)))
+:: ~
+:: Source
+++ iteri
+|* [a=(list) fun=$-(* *)]
+ =/ b (mapi a fun)
+ ~
+:: +iteri2: [(list T1) (list T2) fun:$-(@ T1 T2 *)] -> ~
+::
+:: Applies the given function to two lists and the current index,
+:: dropping the results. The lists must have identical size.
+:: Examples
+:: > %: iteri2
+:: (limo ~[1 2 3])
+:: (limo ~[4 5 6])
+:: |=([a=@ b=@ c=@] (add (add a b) c))
+:: ==
+:: ~
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ iteri2
+ |* [a=(list) b=(list) fun=$-(* *)]
+ =/ b (mapi2 a b fun)
+ ~
+:: +last-n: [(list T) count:@] -> (list T)
+::
+:: Returns the last N elements of the list.
+:: Examples
+:: > (last-n `(list @)`[1 2 3 4 ~] 2)
+:: [i=3 t=~[4]]
+:: > (last-n `(list @)`[1 2 3 4 ~] 10)
+:: [i=1 t=~[2 3 4]]
+:: Source
+++ last-n
+ |* [p=(list) q=@]
+ (flop (scag q (flop p)))
+:: +length: (list T) -> @u
+::
+:: Returns the length of the list.
+:: Examples
+:: > (length [1 2 3 4 ~])
+:: 4
+:: > (length [1 'a' 2 'b' (some 10) ~])
+:: 5
+:: Source
+++ length lent
+:: +map-seq: [(list T1) mapping:$-(T1 T2)] -> (list T2)
+::
+:: Builds a new list whose elements are the results of applying the given
+:: gate to each of the elements of the list.
+:: Examples
+:: > (map (limo [104 111 111 110 ~]) @t)
+:: <|h o o n|>
+:: > =a |=(a=@ (add a 4))
+:: > (map (limo [1 2 3 4 ~]) a)
+:: ~[5 6 7 8]
+:: Source
+++ map-seq turn
+:: +map2: [(list T1) (list T2) mapping:$-([T1 T2] T3)] -> (list T3)
+::
+:: Builds a new list whose elements are the results of applying the given
+:: function to the corresponding elements of the two lists pairwise.
+:: Crashes if lists are of unequal length
+:: Examples
+:: > (map2 (limo ~[1 2 3 4]) (limo ~[5 6 7 8]) |=(a=[@ @] (add -.a +.a)))
+:: ~[6 8 10 12]
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ map2
+ |* [a=(list) b=(list) c=gate]
+ =/ d=(list) ~
+ |-
+ ?~ a ?~ b (flop d) ~|('lists of unequal length' !!)
+ ?~ b ~|('lists of unequal length' !!)
+ $(a t.a, b t.b, d [(c i.a i.b) d])
+:: +map3: [(list T1) (list T2) (list T3) $-([T1 T2 T3] T4)] -> (list T4)
+::
+:: Builds a new list whose elements are the results of applying the given
+:: function to the corresponding elements of the three lists
+:: simultaneously.
+:: Examples
+:: > %: map3
+:: (limo ~[1 2 3 4])
+:: (limo ~[5 6 7 8])
+:: (limo ~[9 10 11 12])
+:: |=(a=[@ @ @] (add (add -.a +<.a) +>.a))
+:: ==
+:: ~[15 18 21 24]
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ map3
+ |* [a=(list) b=(list) c=(list) d=gate]
+ =/ e=(list) ~
+ |-
+ ?~ a ?~ b ?~ c (flop e)
+ ~|('lists of unequal length' !!)
+ ~|('lists of unequal length' !!)
+ ?~ b ~|('lists of unequal length' !!)
+ ?~ c ~|('lists of unequal length' !!)
+ $(a t.a, b t.b, c t.c, e [(d i.a i.b i.c) e])
+:: +map-fold: [(list T1) state:T2 $-([T1 T2] [T3 T2])] -> [(list T3) T2]
+::
+:: Combines map and fold. Builds a new list whose elements are the results of
+:: applying the given function to each of the elements of the input list. The
+:: function is also used to accumulate a final value.
+:: Examples
+:: > =input `(list [@t @])`~[['in' 1] ['out' 2] ['in' 3]]
+:: > =foo |* [p=[@t @] state=@]
+:: ^- [[@t @] @]
+:: ?: =(-.p 'in') [['in' (mul +.p 2)] (add state +.p)]
+:: [['out' (mul +.p 2)] (mul state +.p)]
+:: > (map-fold input 0 foo)
+:: [~[['in' 2] ['out' 4] ['in' 6]] 5]
+:: Source
+++ map-fold spin
+:: +map-fold-back: [(list T1) state:T2 $-([T1 T2] [T3 T2])] -> [(list T3) T2]
+::
+:: Combines map and foldBack. Builds a new list whose elements are the results
+:: of applying the given function to each of the elements of the input list,
+:: starting from the end.
+:: The function is also used to accumulate a final value.
+:: Examples
+:: > =input `(list [@t @])`~[['in' 1] ['out' 2] ['in' 3]]
+:: > =foo |* [p=[@t @] state=@]
+:: ^- [[@t @] @]
+:: ?: =(-.p 'in') [['in' (mul +.p 2)] (add state +.p)]
+:: [['out' (mul +.p 2)] (mul state +.p)]
+:: > (map-fold-back input 0 foo)
+:: [~[['in' 6] ['out' 4] ['in' 2]] 7]
+:: Source
+++ map-fold-back
+ |* [a=(list) state=* c=$-([* *] [* *])]
+ (spin (flop a) state c)
+:: +mapi: [(list T1) mapping:$-([@ T1] T2)] -> (list T2)
+::
+:: Builds a new list whose elements are the results of applying the given
+:: function to each of the elements of the list. The integer index passed
+:: to the function indicates the index (from 0) of element being transformed.
+:: Examples
+:: > (mapi (limo ~[1 2 3]) |=([a=@ b=@] (add a b)))
+:: ~[1 3 5]
+:: Source
+++ mai
+ |* [a=(list) b=gate]
+ =| i=@ud
+ => .(a (homo a))
+ ^- (list _?>(?=(^ a) (b i i.a)))
+ |-
+ ?~ a ~
+ :- i=(b i i.a)
+ t=$(a t.a, i +(i))
+++ mapi
+ |* [a=(list) fun=$-([@ *] *)]
+ =/ i 0
+ =/ b=(list) ~
+ |-
+ ?~ a (flop b)
+ $(a t.a, b [(fun i i.a) b], i +(i))
+:: +mapi2: [(list T1) (list T2) mapping:$-([@ T1 T2] T3)] -> (list T3)
+::
+:: Like mapi, but mapping corresponding elements from two lists of equal length.
+:: Examples
+:: > %: mapi2
+:: (limo ~[1 2 3])
+:: (limo ~[4 5 6])
+:: |=([a=@ b=@ c=@] (add (add a b) c))
+:: ==
+:: ~[5 8 11]
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ mapi2
+ |* [a=(list) b=(list) fun=$-([@ * *] *)]
+ =/ i 0
+ =/ c=(list) ~
+ |-
+ ?~ a ?~ b (flop c) ~|('lists of unequal length' !!)
+ ?~ b ~|('lists of unequal length' !!)
+ $(a t.a, b t.b, c [(fun i i.a i.b) c], i +(i))
+:: +maxi: (list T) -> T
+::
+:: Return the greatest of all elements of the list, compared via Operators.max.
+:: Examples
+:: > (maxi (limo ~[10 12 11]))
+:: 12
+:: > (maxi (limo ~["max" "add" "busy"]))
+:: Crash
+:: 'empty list'
+:: Source
+++ maxi
+ |* a=(list)
+ ~| 'empty list'
+ =/ m -.a
+ |-
+ ?~ a m
+ ?: (aor m i.a) $(m i.a, a t.a)
+ $(a t.a)
+:: +maxBy: [(list T) projection:$-(* *)] -> T
+::
+:: Returns the greatest of all elements of the list, compared via Operators.max
+:: on the function result.
+:: Examples
+:: > (max-by (limo ~["aa" "mmmm" "zzz"]) |=(a=tape (lent a)))
+:: "mmmm"
+:: Crash
+:: 'empty list'
+:: Source
+++ max-by
+ |* [a=(list) q=$-(* *)]
+ ~| 'empty list'
+ =/ m -.a
+ |-
+ ?~ a m
+ ?: (aor (q m) (q i.a)) $(m i.a, a t.a)
+ $(a t.a)
+:: +mini: (list T)
+::
+:: Returns the lowest of all elements of the list, compared via Operators.min.
+:: Examples
+:: > (mini (limo ~[11 12 10]))
+:: 10
+:: > (mini (limo ~["min" "add" "busy"]))
+:: "add"
+:: Crash
+:: 'empty list'
+:: Source
+++ mini
+ |* a=(list)
+ ~| 'empty list'
+ =/ m -.a
+ |-
+ ?~ a m
+ ?. (aor m i.a) $(m i.a, a t.a)
+ $(a t.a)
+:: +minBy: (list T) projection
+::
+:: Returns the lowest of all elements of the list, compared via Operators.min
+:: on the function result
+:: Examples
+:: > (min-by (limo ~["aa" "mmmm" "zzz"]) |=(a=tape (lent a)))
+:: "aa"
+:: Crash
+:: 'empty list'
+:: Source
+++ min-by
+ |* [a=(list) q=$-(* *)]
+ ~| 'empty list'
+ =/ m -.a
+ |-
+ ?~ a m
+ ?. (aor (q m) (q i.a)) $(m i.a, a t.a)
+ $(a t.a)
+:: +pairwise: (list T) -> (list [T T])
+::
+:: Returns a list of each element in the input list and its predecessor, with
+:: the exception of the first element which is only returned as the predecessor
+:: of the second element.
+:: Examples
+:: > (pairwise (limo ~[1 2 3 4]))
+:: ~[[1 2] [2 3] [3 4]]
+:: Source
+++ pairwise
+ |* a=(list)
+ =/ b=(list [_?>(?=(^ a) i.a) _?>(?=(^ a) i.a)]) ~
+ |-
+ ?: (lth (lent a) 2) (flop b)
+ ?~ a ~|('cant get here' !!)
+ ?~ t.a ~|('cant get here' !!)
+ $(a t.a, b [[i.a i.t.a] b])
+:: +partition: [(list T) predicate:$-( T ?)] -> [(list T) (list T)]
+::
+:: Splits the list into two lists, containing the elements for
+:: which the given predicate returns True and False respectively. Element order
+:: is preserved in both of the created lists.
+:: Examples
+:: > =a |=(a=@ (gth a 1))
+:: > (partition `(list @)`[0 1 2 3 ~] a)
+:: [p=[i=2 t=~[3]] q=[i=0 t=~[1]]]
+:: Source
+++ partition skid
+:: +permute: [(list T) projection:$-(@ @)] -> (list T)
+::
+:: Returns a list with all elements permuted according to the permutation
+:: specified by operating on the element indices.
+:: Examples
+:: > (permute (limo ~[1 2 3 4]) |=(i=@ (mod +(i) 4)))
+:: ~[4 1 2 3]
+:: Source
+++ permute
+ |* [a=(list) q=$-(@ @)]
+ =/ b=(list [@ _?>(?=(^ a) i.a)]) ~
+ =/ i 0
+ |-
+ ?~ a +:(unzip (sort b aor))
+ $(a t.a, b [[(q i) i.a] b], i +(i))
+:: +reduce: [(list T) reduction:$-([T T] T)] -> T
+::
+:: Apply a function to each element of the list, threading an accumulator
+:: argument through the computation. Apply the function to the first two
+:: elements of the list. Then feed this result into the function along with the
+:: third element and so on. Return the final result. If the input function is f
+:: and the elements are i0...iN then computes f (... (f i0 i1) i2 ...) iN.
+:: Examples
+:: > %+ reduce
+:: `(list tape)`~["urbit" "is" "fun"]
+:: |=([a=tape b=tape] (welp (snoc a ' ') b))
+:: "urbit is fun"
+:: Crash
+:: 'empty list'
+:: Source
+++ reduce
+ |* [a=(list) q=$-([* *] *)]
+ ?~ a ~|('empty list' !!)
+ =/ b `_?>(?=(^ a) i.a)`i.a
+ =/ c t.a
+ |-
+ ?~ c b
+ $(b (q b i.c), c t.c)
+:: +reduceBack: [(list T) reduction:$-([T T] T)] -> T
+::
+:: Applies a function to each element of the list, starting from the end,
+:: threading an accumulator argument through the computation. If the input
+:: function is f and the elements are i0...iN then computes
+:: f i0 (...(f iN-1 iN)).
+:: Examples
+:: > %+ reduce-back
+:: `(list tape)`~["urbit" "is" "fun"]
+:: |=([a=tape b=tape] (welp (snoc a ' ') b))
+:: "fun is urbit"
+:: Crash
+:: 'empty list'
+:: Source
+++ reduce-back
+ |* [a=(list) q=$-([* *] *)]
+ (reduce (flop a) q)
+:: +remove-at: [(list T) index:@] -> (list T)
+::
+:: Return a new list with the item at a given index removed.
+:: Examples
+:: > (remove-at "good day, urbit!" 8)
+:: "good day urbit!"
+:: > (remove-at `(list @)`[1 2 3 4 ~] 2)
+:: ~[1 2 4]
+:: Crash
+:: 'out of range'
+:: Source
+++ remove-at
+ |* [a=(list) i=@]
+ ?: (gte i (lent a)) ~|('out of range' !!)
+ (oust [i 1] a)
+:: +remove-many-at: [(list T) index=@ count=@] -> (list T)
+::
+:: Return a new list with the number of items starting at a given index removed
+:: Examples
+:: > (remove-many-at "good day, urbit!" [4 5])
+:: "good urbit!"
+:: > (remove-many-at `(list @)`[1 2 3 4 ~] [2 2])
+:: ~[1 2]
+:: Crash
+:: 'out of range'
+:: Source
+++ remove-many-at
+ |* [a=(list) i=@ c=@]
+ ?: (gth (add i c) (lent a)) ~|('out of range' !!)
+ (oust [i c] a)
+:: +replicate: [count=@ initial=T] -> (list T)
+::
+:: Creates a list by replicating the given initial value.
+:: Examples
+:: > (replicate 20 %a)
+:: ~[%a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a]
+:: > (replicate 5 ~s1)
+:: ~[~s1 ~s1 ~s1 ~s1 ~s1]
+:: > `@dr`(roll (replicate 5 ~s1) add)
+:: ~s5
+:: Source
+++ replicate reap
+:: +reverse: (list T) -> (list T)
+::
+:: Returns a new list with the elements in reverse order.
+:: Examples
+:: > =a [1 2 3 ~]
+:: > (flop a)
+:: ~[3 2 1]
+:: > (flop (flop a))
+:: ~[1 2 3]
+:: Source
+++ reverse flop
+:: +scanx: [(list T1) state:T2 folder:$-([T1 T2] T2)] -> (list T2)
+::
+:: Applies a function to each element of the list and an accumulator, threading
+:: the accumulator argument through the computation. Returns the list of
+:: intermediate results and the final result.
+:: Examples
+:: > %: scanx
+:: `(list tape)`~["urbit" "is" "fun"]
+:: ""
+:: |=([a=tape b=tape] (welp (snoc b ' ') a))
+:: ==
+:: ~["" " urbit" "urbit is" " urbit is fun"]
+:: Source
+++ scanx
+ |* [a=(list) state=* fun=$-([* *] *)]
+ =/ b=(list _state) ~
+ |- ^- (list _?>(?=(^ a) i.a))
+ ?~ a (flop [state b])
+ $(a t.a, b [state b], state (fun i.a state))
+:: +scan-back: [(list T) state:T2 folder:$-(T1 T2)] -> (list T2)
+::
+:: Like fold-back, but returns both the intermediary and final results
+:: Examples
+:: Source
+++ scan-back
+ |* [a=(list) state=* fun=$-([* *] *)]
+ =/ c=(list _?>(?=(^ a) i.a)) (flop a)
+ =/ b=(list _state) ~
+ |- ^- (list _?>(?=(^ a) i.a))
+ ?~ c (flop [state b])
+ $(c t.c, b [state b], state (fun i.c state))
+:: +singleton: value: T -> (list T)
+::
+:: Returns a list that contains one item only.
+:: Examples
+:: > (singleton "tape")
+:: ~["tape"]
+:: Source
+++ singleton
+ |* a=*
+ (limo ~[a])
+:: +skip-n: [(list T) count:@] -> (list T)
+::
+:: Returns the list after removing the first N elements.
+:: Examples
+:: > (skip-n `(list @)`[1 2 3 4 ~] 2)
+:: ~[3 4]
+:: Crash
+:: 'out of range'
+:: Source
+++ skip-n
+ |* [p=(list) q=@]
+ ?~ p ?~ q p ~|('out of range' !!)
+ ?~ q p
+ $(p t.p, q (dec q))
+:: +skip-while: [(list T) predicate:$-(T ?)] -> (list T)
+::
+:: Bypasses elements in a list while the given predicate returns True, and then
+:: returns the remaining elements of the list.
+:: Examples
+:: > %: skip-while
+:: (limo ~["a" "bbb" "cc" "d"])
+:: |=(a=tape (lth (lent a) 3))
+:: ==
+:: ~["bbb" "cc" "d"]
+:: Source
+++ skip-while
+ |* [a=(list) b=$-(* ?)]
+ =/ c=(list _?>(?=(^ a) i.a)) ~
+ |- ^+ a
+ ?~ a (flop c)
+ ?~ c ?: (b i.a) $(a t.a) $(a t.a, c [i.a c])
+ $(a t.a, c [i.a c])
+:: +sort-by: [(list T) projection:$-(T *)] -> (list T)
+::
+:: Sorts the given list using keys given by the given projection. Keys are
+:: compared using Operators.compare.
+:: Examples
+:: > (sort-by (limo ~["bb" "a" "dddd" "ccc"]) |=(a=tape (lent a)))
+:: ~["a" "bb" "ccc" "dddd"]
+:: Source
+++ sort-by
+ |* [a=(list) proj=$-(* *)]
+ =/ b (turn a proj)
+ =/ c (zip b a)
+ +:(unzip (sort c aor))
+:: +sort-by-descending: [(list T) projection:$-(T *)] -> (list T)
+::
+:: Sorts the given list in descending order using keys given by the given
+:: projection. Keys are compared using Operators.compare.
+:: Examples
+:: > %: sort-by-descending
+:: (limo ~["bb" "a" "dddd" "ccc"]) |=(a=tape (lent a))
+:: ==
+:: ~["dddd" "ccc" "bb" "a"]
+:: Source
+++ sort-by-descending
+ |* [a=(list) proj=$-(* *)]
+ =/ b (turn a proj)
+ =/ c (zip b a)
+ +:(unzip (sort c |=([a=* b=*] (aor b a))))
+:: +sort-descending: (list T) -> (list T)
+::
+:: Sorts the given list in descending order using Operators.compare.
+:: Examples
+:: > (sort-descending (limo ~[4 2 1 3]))
+:: ~[4 3 2 1]
+:: Source
+++ sort-descending
+ |* a=(list)
+ (sort a |=([a=* b=*] (aor b a)))
+:: +sort-qik: (list T) -> (list T)
+::
+:: Sorts the given list in ascending order using Operators.compare.
+:: Examples
+:: > (sort-qik (limo ~[4 2 1 3]))
+:: ~[1 2 3 4]
+:: Source
+++ sort-qik
+ |* a=(list)
+ (sort a aor)
+:: +split-at: [(list T) index:@] -> [(list T) (list T)]
+::
+:: Splits a list into two lists, at the given index.
+:: Examples
+:: > (split-at (limo ~[1 2 3 4 5]) 2)
+:: [~[1 2] ~[3 4 5]]
+:: Source
+++ split-at
+ |* [p=(list) i=@]
+ [(scag i p) (slag i p)]
+:: +split-into: [(list T) count:@] -> (list (list T))
+::
+:: Splits the input list into at most count chunks.
+:: Examples
+:: > (split-into (gulf 1 10) 4)
+:: Crash
+:: 'count is 0'
+:: Source
+++ split-into
+ |* [a=(list) i=@]
+ ?~ i ~|('count is 0' !!)
+ =/ b=(list (list _?>(?=(^ a) i.a))) ~
+ |-
+ ?: =(0 (lent a)) (flop b)
+ =/ q (div (lent a) i)
+ =/ r (mod (lent a) i)
+ =/ l ?: =(0 r) q +(q)
+ =/ c=(list _?>(?=(^ a) i.a)) ~
+ |-
+ ?~ l ^$(b [(flop c) b], i (dec i))
+ ?~ a ?~ c (flop b) (flop [(flop c) b])
+ $(c [i.a c], l (dec l), a t.a)
+:: +sum: (list @) -> @
+::
+:: Returns the sum of the elements in the list.
+:: Examples
+:: > (sum (limo ~[1 2 3]))
+:: 6
+:: Source
+++ sum
+ |* a=(list @)
+ =/ b=@ 0
+ |-
+ ?~ a b
+ $(a t.a, b (add b i.a))
+:: +sum-by: [(list T) projection:$-(T @)] -> @
+::
+:: Returns the sum of the results generated by applying the function to each
+:: element of the list.
+:: Examples
+:: > (sum-by (limo ~["a" "bb" "ccc"]) |=(a=tape (lent a)))
+:: 6
+:: Source
+++ sum-by
+ |* [a=(list) proj=$-(* @)]
+ =/ b=@ 0
+ |-
+ ?~ a b
+ $(a t.a, b (add b (proj i.a)))
+:: +tail-end: (list T) -> T
+::
+:: Returns the last element of the list.
+:: Crash when the input does not have any elements.
+:: Examples
+:: > (last ~[1 2 3])
+:: 3
+:: Crash
+:: 'empty list'
+:: Source
+++ tail-end
+ |* a=(list)
+ ?~ a ~|('empty list' !!)
+ (rear a)
+:: +take-while: [(list T) predicate:$-(T ?)] -> (list T)
+::
+:: Returns a list that contains all elements of the original list while the
+:: given predicate returns True, and then returns no further elements.
+:: Examples
+:: > %: take-while
+:: (limo ~["a" "bb" "ccc" "d"])
+:: |=(a=tape (lth (lent a) 3))
+:: ==
+:: ~["a" "bb"]
+:: Source
+++ take-while
+ |* [a=(list) b=$-(* ?)]
+ =/ c=(list _?>(?=(^ a) i.a)) ~
+ |- ^+ a
+ ?~ a (flop c)
+ ?: (b i.a) $(a t.a, c [i.a c])
+ (flop c)
+:: +to-map: (list [* *]) ->
+::
+:: Produces a map from a list.
+:: Examples
+:: > (to-map (limo ~[['aa' 1] ['bb' 2] ['cc' 3] ['dd' 4]]))
+:: [n=[p='dd' q=4] l=[n=[p='cc' q=3] l=[n=[p='aa' q=1] l=~ r=~] r=~]
+:: r=[n=[p='bb' q=2] l=~ r=~]]
+:: Source
+++ to-map
+ |* a=(list)
+ (malt a)
+:: +to-set: (list) ->
+::
+:: Produces a set from a list.
+:: Examples
+:: > (to-map (limo ~[['aa' 1] ['bb' 2] ['cc' 3] ['dd' 4]]))
+:: [n=['dd' 4] l=[n=['cc' 3] l=[n=['aa' 1] ~ ~] ~] r=[n=['bb' 2] ~ ~]]
+:: Source
+++ to-set
+ |* a=(list)
+ (silt a)
+:: +transpose: (list (list T)) -> ?([~ ~] (list (list T)))
+::
+:: Returns the transpose of the given sequence of lists.
+:: Returns [~ ~] when all lists of list are ~.
+:: Examples
+:: > %- transpose
+:: %: limo
+:: (limo ~["a" "b" "c"])
+:: (limo ~["aa" "bb" "cc"])
+:: (limo ~["aaa" "bbb" "ccc"])
+:: ~
+:: ==
+:: ~[~["a" "aa" "aaa"] ~["b" "bb" "bbb"] ~["c" "cc" "ccc"]]
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ transpose
+ |* a=(list (list))
+ =/ aa a
+ =/ equal=? %.y
+ ~| 'lists of unequal length'
+ |- ^- (list (list _?>(?=(^ ^ a) -.-.a)))
+ ?: =(%.n equal) !!
+ ?~ aa (transpose-jgd a)
+ ?~ t.aa (transpose-jgd a)
+ ?: =((lent i.aa) (lent i.t.aa)) $(aa t.aa) $(equal %.n)
+:: +transpose-jgd: (list (list T)) -> ?([~ ~] (list (list T)))
+::
+:: Returns the jagged transpose of the given sequence of lists.
+:: Returns [~ ~] when all lists of list are ~.
+:: Examples
+:: > %- transpose-jgd
+:: %: limo
+:: (limo ~["a" "b" "c"])
+:: (limo ~["aa" "cc"])
+:: (limo ~["aaa" "bbb" "ccc"])
+:: ~
+:: ==
+:: ~[~["a" "aa" "aaa"] ~["b" "cc" "bbb"] ~["c" "ccc"]]
+:: Source
+++ transpose-jgd
+ |* a=(list (list))
+ =/ aa=(list (list _?>(?=(^ ^ a) -.-.a))) a
+ =/ b=(list (list _?>(?=(^ ^ a) -.-.a))) ~
+ =/ bb=(list _?>(?=(^ ^ a) -.-.a)) ~
+ |- ^- (list (list _?>(?=(^ ^ a) -.-.a)))
+ ?~ a (flop b)
+ =/ c=(list (list _?>(?=(^ ^ a) -.-.a))) ~
+ |-
+ ?~ aa
+ %= ^$
+ a (flop c)
+ aa (flop c)
+ b [(flop bb) b]
+ bb ~
+ ==
+ ?~ -.aa $(aa t.aa)
+ ?~ ->.aa $(aa t.aa, bb [-<.aa bb])
+ $(aa t.aa, bb [-<.aa bb], c [->.aa c])
+:: +try-exactly-one: (list T) -> (unit T)
+::
+:: Returns the only element of the list or None if it is empty or contains more
+:: than one element.
+:: Examples
+:: > (try-exactly-one (limo ~["tape"]))
+:: [~ i=[i=t' t="ape"]]
+:: Source
+++ try-exactly-one
+ |* a=(list)
+ ?: =(1 (lent a)) `-.a
+ ~
+:: +try-find: [(list T) predicate:$-(T ?)] -> (unit T)
+::
+:: Returns the first element for which the given function returns True.
+:: Return None if no such element exists.
+:: Examples
+:: > (try-find (gulf [1 30]) |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5)))))
+:: `15
+:: Source
+++ try-find
+ |* [a=(list) b=$-(* ?)]
+ |- ^- (unit _?>(?=(^ a) i.a))
+ ?~ a ~
+ ?: (b i.a) `i.a $(a t.a)
+:: +try-find-back: [(list T) predicate:$-(T ?)] -> (unit T)
+::
+:: Returns the last element for which the given function returns True.
+:: Return None if no such element exists.
+:: Examples
+:: > %: try-find-back
+:: (gulf [1 30])
+:: |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5))))
+:: ==
+:: `30
+:: Source
+++ try-find-back
+ |* [a=(list) b=$-(* ?)]
+ ?~ a ~
+ (try-find (flop a) b)
+:: +try-find-by-unit: [(list T) chooser:$-(T (unit T))] -> (unit T)
+::
+:: Applies the given function to successive elements, returning Some(x) for the
+:: first result where function returns Some(x).
+:: If no such element exists then return None.
+:: Examples
+:: > (search-by-unit (limo ~[1 2 3 4]) |=(a=@ ?:(=((mod a 2) 0) `a ~)))
+:: `2
+:: Crash
+:: 'not found'
+:: Source
+++ try-find-by-unit
+ |* [hstk=(list) nedl=$-(* (unit *))]
+ |- ^- (unit _?>(?=(^ hstk) i.hstk))
+ ?~ hstk ~
+ =/ x (nedl i.hstk)
+ ?~ x $(hstk t.hstk) x
+:: +try-find-index: [(list T) predicate:$-(T ?)] -> (unit @)
+::
+:: Returns the index of the first element in the list that satisfies the given
+:: predicate. Return None if no such element exists.
+:: Examples
+:: > %: try-find-index
+:: (gulf [1 30])
+:: |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5))))
+:: ==
+:: `14
+:: Source
+++ try-find-index
+ |* [a=(list) b=$-(* ?)]
+ =/ i 0
+ |- ^- (unit @)
+ ?~ a ~
+ ?: (b i.a) `i $(a t.a, i +(i))
+:: +try-find-index-back: [(list T) predicate:$-(T ?)] -> (unit @)
+::
+:: Returns the index of the last element in the list that satisfies the given
+:: predicate. Return None if no such element exists.
+:: Examples
+:: > %: try-find-index-back
+:: (gulf [1 30])
+:: |=(a=@ud ?&(=(0 (mod a 3)) =(0 (mod a 5))))
+:: ==
+:: `29
+:: Source
+++ try-find-index-back
+ |* [a=(list) c=$-(* ?)]
+ ?~ a ~
+ =/ b (flop a)
+ =/ i (dec (lent a))
+ |- ^- (unit @ud)
+ ?~ b ~
+ ?: (c i.b) `i
+ ?: =(0 i) ~
+ $(b t.b, i (dec i))
+:: +try-head: (list T) -> (unit T)
+::
+:: Returns the first element of the list, or None if the list is empty.
+:: Examples
+:: > (try-head ~[1 2])
+:: `1
+:: Source
+++ try-head
+ |* a=(list)
+ ?~ a ~
+ `i.a
+:: +try-item: [(list T) index:@] -> (unit T)
+::
+:: Tries to find the nth element in the list. Returns None if index is negative
+:: or the list does not contain enough elements.
+:: Examples
+:: > (try-item `(list @)`~["aa" "bb" "cc" "dd"] 2)
+:: [~ "cc"]
+:: > (try-item `(list tape)`~["aa" "bb"] 2)
+:: ~
+:: Source
+++ try-item
+ |* [a=(list) i=@]
+ ?: (gte i (lent a)) ~
+ `(snag i a)
+:: +try-remove-at: [(list T) index:@] -> (unit (list T))
+::
+:: Attempt a new list with the item at a given index removed returning
+:: Some((list T)) upon success.
+:: Examples
+:: > (try-remove-at "good day, urbit!" 8)
+:: [~ "good day urbit!"]
+:: > (try-remove-at `(list @)`[1 2 3 4 ~] 2)
+:: [~ ~[1 2 4]]
+:: Source
+++ try-remove-at
+ |* [a=(list) i=@]
+ ?: (gte i (lent a)) ~
+ `(oust [i 1] a)
+:: +try-remove-many-at: [(list T) index=@ count=@] -> (list T)
+::
+:: Return a new list with the number of items starting at a given index removed
+:: returning Some((list T)) upon success.
+:: Examples
+:: > (try-remove-many-at "good day, urbit!" [4 5])
+:: [~ "good urbit!"]
+:: > (try-remove-many-at `(list @)`[1 2 3 4 ~] [2 2])
+:: [~ ~[1 2]]
+:: Source
+++ try-remove-many-at
+ |* [a=(list) i=@ c=@]
+ ?: (gth (add i c) (lent a)) ~
+ `(oust [i c] a)
+:: +try-tail: (list T) -> (unit (list T))
+::
+:: Returns the elements of the list after the first.
+:: Examples
+:: > (try-tail ~[1 2])
+:: `~[2]
+:: Source
+++ try-tail
+ |* a=(list)
+ ?~ a ~
+ `t.a
+:: +try-tail-end: (list T) -> (unit T)
+::
+:: Returns the last element of the list. Return None if no such element exists.
+:: Examples
+:: > (try-tail-end ~[1 2 3])
+:: `3
+:: Source
+++ try-tail-end
+ |* a=(list)
+ ?~ a ~
+ `(rear a)
+:: +try-update-at: [(list T) index:@ value:T] -> (list T)
+::
+:: Return a new list with the item at a given index set to the new value.
+:: Examples
+:: > (try-update-at (limo ~[2 3 4]) 1 11)
+:: [~ ~[2 11 4]]
+:: > (try-update-at (limo ~[2 3 4]) 3 11)
+:: ~
+:: Crash
+:: 'not found'
+:: Source
+++ try-update-at
+ |* [a=(list) b=@ c=*]
+ ?: (gte b (lent a)) ~
+ `(snap a b c)
+:: +unfold: [state:T1 generator:$-(T1 -> (unit [T1 T2]))] -> (list T2)
+::
+:: Returns a list that contains the elements generated by the given computation
+:: The generator is repeatedly called to build the list until it returns None.
+:: The given initial state argument is passed to the element generator.
+:: Examples
+:: > (unfold 1 |=(a=@ ?:((gth a 100) ~ `[(mul a 2) a])))
+:: ~[1 2 4 8 16 32 64]
+:: Source
+++ unfold
+ |* [state=* gen=$-(* (unit [* *]))]
+ =/ res=(list) ~
+ |-
+ =/ x (gen state)
+ ?~ x (flop res)
+ =/ y (need x)
+ $(state -.y, res [+.y res])
+:: +unzip: (list [T1 T2]) - [(list T1) (list T2)]
+::
+:: Splits a list of pairs into two lists.
+:: Examples
+:: > (unzip (limo ~[[1 "aa"] [2 "bb"]]))
+:: [~[1 2] ~["aa" "bb"]]
+:: Source
+++ unzip
+ |* a=(list [* *])
+ =/ b=(list *) ~
+ =/ c=(list *) ~
+ |-
+ ?~ a [(flop b) (flop c)]
+ $(a t.a, b [-.i.a b], c [+.i.a c])
+:: +unzip3: (list [T1 T2 T3]) - [(list T1) (list T2) (list T3)]
+::
+:: Splits a list of triples into three lists.
+:: Examples
+:: > (unzip3 (limo ~[[1 "aa" 'a'] [2 "bb" 'b']]))
+:: [~[1 2] ~["aa" "bb"] ~['a' 'b']]
+:: Source
+++ unzip3
+ |* a=(list [* *])
+ =/ b=(list *) ~
+ =/ c=(list *) ~
+ =/ d=(list *) ~
+ |-
+ ?~ a [(flop b) (flop c) (flop d)]
+ $(a t.a, b [-.i.a b], c [+<.i.a c], d [+>.i.a d])
+:: +update-at: [(list T) index:@ value:T] -> (list T)
+::
+:: Return a new list with the item at a given index set to the new value.
+:: Examples
+:: > (update-at (limo ~[2 3 4]) 1 11)
+:: ~[2 11 4]
+:: Crash
+:: 'not found'
+:: Source
+++ update-at
+ |* [a=(list) b=@ c=*]
+ ?: (gte b (lent a)) ~|('not found' !!)
+ (snap a b c)
+:: +windowed: [(list T) window-size:@] -> (list (list T))
+::
+:: Returns a list of sliding windows containing elements drawn from the input
+:: list. Each window is returned as a fresh list.
+:: Examples
+:: > (windowed (limo ~[1 2 3 4 5]) 3)
+:: ~[~[1 2 3] ~[2 3 4] ~[3 4 5]]
+:: Crash
+:: 'empty list'
+:: 'window length is 0'
+:: 'list shorter than window'
+:: Source
+++ windowed
+ |* [p=(list *) q=@]
+ ?~ q ~|('window length is 0' !!)
+ =/ b=(list (list _?>(?=(^ p) i.p))) ~
+ =/ sub-tree=(list _?>(?=(^ p) i.p)) ~
+ =/ pp=(list _?>(?=(^ p) i.p)) p
+ |- ^- (list (list _?>(?=(^ p) i.p)))
+ ?~ p ~|('empty list' !!)
+ ?~ pp ?: (lth (lent sub-tree) q)
+ ?~ b ~|('list shorter than window' !!) (flop b)
+ $(pp t.p, b [(flop sub-tree) b], sub-tree ~)
+ ?: =((lent sub-tree) q)
+ $(p t.p, pp t.p, b [(flop sub-tree) b], sub-tree ~)
+ $(pp t.pp, sub-tree [i.pp sub-tree])
+:: +zip: [(list T1) (list T2)] -> (list [T1 T2])
+::
+:: Combines the two lists into a list of pairs. The two lists must have equal
+:: lengths.
+:: Examples
+:: > (zip `(list @)`~[1 2] `(list @)`~["aa" "bb"])
+:: ~[[1 "aa"] [2 "bb"]]
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ zip
+ |* [a=(list) b=(list)]
+ =/ c=(list [_?>(?=(^ a) i.a) _?>(?=(^ b) i.b)]) ~
+ |- ^- (list [_?>(?=(^ a) i.a) _?>(?=(^ b) i.b)])
+ ?~ a ?~ b (flop c) ~|('lists of unequal length' !!)
+ ?~ b ~|('lists of unequal length' !!)
+ $(a t.a, b t.b, c [[i.a i.b] c])
+:: +zip3: [(list T1) (list T2) (list T3)] -> (list [T1 T2 T3])
+::
+:: Combines the three lists into a list of triples. The lists must have equal
+:: lengths.
+:: Examples
+:: > %: zip3
+:: `(list @)`~[1 2]
+:: `(list tape)`~["aa" "bb"]
+:: `(list @t)`~['a' 'b']
+:: ==
+:: ~[[1 "aa" 'a'] [2 "bb" 'b']]
+:: Crash
+:: 'lists of unequal length'
+:: Source
+++ zip3
+ |* [a=(list) b=(list) c=(list)]
+ =/ d=(list [_?>(?=(^ a) i.a) _?>(?=(^ b) i.b) _?>(?=(^ c) i.c)]) ~
+ |- ^- (list [_?>(?=(^ a) i.a) _?>(?=(^ b) i.b) _?>(?=(^ c) i.c)])
+ ?~ a ?~ b ?~ c (flop d)
+ ~|('lists of unequal length' !!)
+ ~|('lists of unequal length' !!)
+ ?~ b ~|('lists of unequal length' !!)
+ ?~ c ~|('lists of unequal length' !!)
+ $(a t.a, b t.b, c t.c, d [[i.a i.b i.c] d])
+-- \ No newline at end of file