& the very base: know something's type & fn type { & "Returns a keyword representing the type of the value passed in." & (x) -> base :type (x) & } & & some helper type functions & fn coll? { & "Returns true if a value is a collection: dict, list, tuple, or set." & (coll as :dict) -> true & (coll as :list) -> true & (coll as :tuple) -> true & & (coll as :set) -> true & (_) -> false & } & fn ordered? { & "Returns true if a value is an indexed collection: list or tuple." & (coll as :list) -> true & (coll as :tuple) -> true & (coll as :string) -> true & (_) -> false & } & fn assoc? { & "Returns true if a value is an associative collection: a dict or a pkg." & (d as :dict) -> true & (_) -> false & } & &&& nil: working with nothing & fn nil? { & "Returns true if a value is nil." & (nil) -> true & (_) -> false & } & fn some? { & "Returns true if a value is not nil." & (nil) -> false & (_) -> true & } & fn some { & "Takes a possibly nil value and a default value. Returns the value if it's not nil, returns the default if it's nil." & (nil, default) -> default & (value, _) -> value & } & ...and if two things are the same fn eq? { "Returns true if all arguments have the same value." & (x) -> true (x, y) -> base :eq? (x, y) & (x, y, ...zs) -> if eq? (x, y) & then loop (y, zs) with { & (a, []) -> eq? (a, x) & (a, [b, ...cs]) -> if eq? (a, x) & then recur (b, cs) & else false & } & else false } & &&& true & false: boolean logic (part the first) & fn bool? { & "Returns true if a value is of type :boolean." & (false) -> true & (true) -> true & (_) -> false & } & fn true? { & "Returns true if a value is boolean `true`. Useful to distinguish between `true` and anything else." & (true) -> true & (_) -> false & } & fn false? { & "Returns `true` if a value is `false`, otherwise returns `false`. Useful to distinguish between `false` and `nil`." & (false) -> true & (_) -> false & } & fn bool { & "Returns false if a value is nil or false, otherwise returns true." & (nil) -> false & (false) -> false & (_) -> true & } & fn not { & "Returns false if a value is truthy, true if a value is falsy." & (nil) -> true & (false) -> true & (_) -> false & } & & tuples: not a lot you can do with them functionally & fn tuple? { & "Returns true if a value is a tuple." & (tuple as :tuple) -> true & (_) -> false & } & &&& functions: getting things done & fn fn? { & "Returns true if an argument is a function." & (f as :fn) -> true & (_) -> false & } & what we need for some very basic list manipulation fn first { "Retrieves the first element of an ordered collection--a tuple or a list. If the collection is empty, returns nil." ([]) -> nil & (()) -> nil & ("") -> nil (xs as :list) -> base :first (xs) & (xs as :tuple) -> base :first (xs) & (str as :string) -> base :slice (str, 0, 1) } fn rest { "Returns all but the first element of a list or tuple, as a list." ([]) -> [] & (()) -> () (xs as :list) -> base :rest (xs) & (xs as :tuple) -> base :rest (xs) & (str as :string) -> base :rest (str) } fn inc { "Increments a number." (x as :number) -> base :inc (x) } & fn dec { & "Decrements a number." & (x as :number) -> base :dec (x) & } & fn count { & "Returns the number of elements in a collection (including string)." & (xs as :list) -> base :count (xs) & (xs as :tuple) -> base :count (xs) & (xs as :dict) -> base :count (xs) & (xs as :string) -> base :count (xs) & & (xs as :set) -> base :count (xs) & } & fn empty? { & "Returns true if something is empty. Otherwise returns false (including for things that can't logically be empty, like numbers)." & ([]) -> true & (#{}) -> true & & (s as :set) -> eq? (s, ${}) & (()) -> true & ("") -> true & (_) -> false & } & fn any? { & "Returns true if something is not empty, otherwise returns false (including for things that can't be logically full, like numbers)." & ([...]) -> true & (#{...}) -> true & & (s as :set) -> not (empty? (s)) & ((...)) -> true & (s as :string) -> not (empty? (s)) & (_) -> false & } & fn list? { & "Returns true if the value is a list." & (l as :list) -> true & (_) -> false & } & fn list { & "Takes a value and returns it as a list. For values, it simply wraps them in a list. For collections, conversions are as follows. A tuple->list conversion preservers order and length. Unordered collections do not preserve order: sets and dicts don't have predictable or stable ordering in output. Dicts return lists of (key, value) tuples." & (x) -> base :list (x) & } fn append { "Adds an element to a list." () -> [] (xs as :list) -> xs (xs as :list, x) -> base :append (xs, x) } fn fold { "Folds a list." (f as :fn, []) -> [] (f as :fn, xs as :list) -> fold (f, xs, f ()) (f as :fn, [], root) -> [] (f as :fn, xs as :list, root) -> loop (root, first (xs), rest (xs)) with { (prev, curr, []) -> f (prev, curr) (prev, curr, remaining) -> recur ( f (prev, curr) first (remaining) rest (remaining) ) } } & fn map { & "Maps a function over a list: returns a new list with elements that are the result of applying the function to each element in the original list. E.g., `map ([1, 2, 3], inc) &=> [2, 3, 4]`. With one argument, returns a function that is a mapper over lists; with two, it executes the mapping function right away." & & (f as :fn) -> map (f, _) & & (kw as :keyword) -> map (kw, _) & (f as :fn, xs) -> { & fn mapper (prev, curr) -> append (prev, f (curr)) & fold (mapper, xs, []) & } & & (kw as :keyword, xs) -> { & & fn mapper (prev, curr) -> append (prev, kw (curr)) & & fold (mapper, xs, []) & & } & } & fn filter { & "Takes a list and a predicate function, and returns a new list with only the items that produce truthy values when the function is called on them. E.g., `filter ([1, 2, 3, 4], odd?) &=> [1, 3]`." & (p? as :fn) -> filter (p?, _) & (p? as :fn, xs) -> { & fn filterer (filtered, x) -> if p? (x) & then append (filtered, x) & else filtered & fold (filterer, xs, []) & } & } & fn keep { & "Takes a list and returns a new list with any `nil` values omitted." & (xs) -> filter (some?, xs) & } & fn concat { & "Combines two lists, strings, or sets." & (x as :string, y as :string) -> "{x}{y}" & (xs as :list, ys as :list) -> base :concat (xs, ys) & & (xs as :set, ys as :set) -> base :concat (xs, ys) & (xs, ys, ...zs) -> fold (concat, zs, concat (xs, ys)) & } fn contains? { "Returns true if a set or list contains a value." & (value, s as :set) -> bool (base :get (s, value)) (value, l as :list) -> loop (l) with { ([]) -> false ([...xs]) -> if eq? (first(xs), value) then true else recur (rest (xs)) } } fn add { () -> 0 (x) -> x (x, y) -> base :add (x, y) } #{ & type & coll? & ordered? & assoc? & nil? & some? & some eq? & bool? & true? & false? & bool & not & tuple? & fn? first rest & inc & dec & count & empty? & any? & list? & list & first & fold & append & map & filter & keep & concat & contains? add }