333 lines
7.3 KiB
Plaintext
333 lines
7.3 KiB
Plaintext
& 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, [b]) -> and (eq? (a, x), eq? (b, 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 foldr {
|
|
"Folds a list, right-associatively."
|
|
(f as :fn, []) -> []
|
|
(f as :fn, xs as :list) -> foldr(f, xs, f ())
|
|
(f as :fn, [], root) -> []
|
|
(f as :fn, xs as :list, root) -> loop (root, first (xs), rest (xs)) with {
|
|
(prev, curr, []) -> f (curr, prev)
|
|
(prev, curr, remaining) -> recur (
|
|
f (curr, prev)
|
|
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 print! {
|
|
"Sends a text representation of Ludus values to the console."
|
|
(...args) -> {
|
|
base :print! (args)
|
|
:ok
|
|
}
|
|
}
|
|
|
|
& fn show {
|
|
& "Returns a text representation of a Ludus value as a string."
|
|
& (x) -> base :show (x)
|
|
& }
|
|
|
|
& fn report! {
|
|
& "Prints a value, then returns it."
|
|
& (x) -> {
|
|
& print! (x)
|
|
& x
|
|
& }
|
|
& (msg as :string, x) -> {
|
|
& print! (concat ("{msg} ", show (x)))
|
|
& x
|
|
& }
|
|
& }
|
|
|
|
#{
|
|
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
|
|
foldr
|
|
append
|
|
map
|
|
filter
|
|
keep
|
|
concat
|
|
contains?
|
|
print!
|
|
& show
|
|
& report!
|
|
}
|