rudus/assets/test_prelude.ld
2025-06-22 21:15:17 -04:00

359 lines
7.9 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
}
}
fn doc! {
"Prints the documentation of a function to the console."
(f as :fn) -> do f > base :doc! > print!
(_) -> :none
}
&&& strings: harder than they look!
fn string? {
"Returns true if a value is a string."
(x as :string) -> true
(_) -> false
}
fn string {
"Converts a value to a string by using `show`. If it is a string, returns it unharmed. Use this to build up strings of different kinds of values."
(x as :string) -> x
(x) -> show (x)
(x, ...xs) -> loop (string (x), xs) with {
(out, [y]) -> concat (out, show (y))
(out, [y, ...ys]) -> recur (concat (out, show (y)), ys)
}
}
#{
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!
doc!
string
string?
}