time
Monotonic clock utilities.
The values come from the platform monotonic clock, so they are useful for measuring elapsed time. They are not wall-clock timestamps.
Functions
pub fn now_ms() -> IntReturn the current monotonic clock value in milliseconds.
time.now_ms()
pub fn now_us() -> IntReturn the current monotonic clock value in microseconds.
time.now_us()
dict
Generic association list dictionary.
Keys are compared using a caller-supplied equality function: for Int keys: fn(a: Int, b: Int) -> a == b for String keys: fn(a: String, b: String) -> string.equal(a, b)
All operations are O(n), suitable for small-to-medium maps.
Types
pub type Dict(k, v)An association list: each entry stores a key, value, and pointer to the rest.
EmptyEntry(k, v, Dict(k, v))Functions
pub fn new() -> Dict(k, v)Create an empty dictionary.
dict.new()
pub fn insert(d: Dict(k, v), key: k, val: v, eq: fn(k, k) -> Bool) -> Dict(k, v)Insert or update a key. If the key already exists (per eq), its value is replaced.
dict.insert(dict.new(), "name", "Donna", fn(a: String, b: String) -> string.equal(a, b))
pub fn get(d: Dict(k, v), key: k, default: v, eq: fn(k, k) -> Bool) -> vLook up a key, returning the value or a default if not found.
dict.get(users, "name", "missing", fn(a: String, b: String) -> string.equal(a, b))
pub fn has_key(d: Dict(k, v), key: k, eq: fn(k, k) -> Bool) -> BoolReturn True if the key is present.
dict.has_key(users, "name", fn(a: String, b: String) -> string.equal(a, b))
pub fn delete(d: Dict(k, v), key: k, eq: fn(k, k) -> Bool) -> Dict(k, v)Remove a key from the dictionary. No-op if not present.
dict.delete(users, "name", fn(a: String, b: String) -> string.equal(a, b))
pub fn size(d: Dict(k, v)) -> IntReturn the number of entries.
dict.size(users)
pub fn is_empty(d: Dict(k, v)) -> BoolReturn True if the dictionary has no entries.
dict.is_empty(dict.new())
pub fn keys(d: Dict(k, v)) -> List(k)Return all keys as a list (insertion order reversed).
dict.keys(users)
pub fn values(d: Dict(k, v)) -> List(v)Return all values as a list (insertion order reversed).
dict.values(users)
pub fn to_list(d: Dict(k, v)) -> List(#(k, v))Convert to a list of key-value pairs.
dict.to_list(users)
pub fn from_list(pairs: List(#(k, v)), eq: fn(k, k) -> Bool) -> Dict(k, v)Build a dictionary from a list of key-value pairs. Later entries in the list take precedence over earlier ones for the same key.
dict.from_list([#("name", "Donna")], fn(a: String, b: String) -> string.equal(a, b))
pub fn merge(base: Dict(k, v), other: Dict(k, v), eq: fn(k, k) -> Bool) -> Dict(k, v)Merge two dicts: entries in other override entries in base for duplicate keys.
dict.merge(base, overrides, fn(a: String, b: String) -> string.equal(a, b))
pub fn map_values(d: Dict(k, v), f: fn(v) -> b) -> Dict(k, b)Apply a function to every value, returning a new dict with the same keys.
dict.map_values(scores, fn(n: Int) -> n + 1)
pub fn filter(d: Dict(k, v), f: fn(k, v) -> Bool) -> Dict(k, v)Keep only entries where f(key, value) returns True.
dict.filter(scores, fn(k: String, v: Int) -> v > 0)
pub fn fold(d: Dict(k, v), init: b, f: fn(b, k, v) -> b) -> bFold over all entries, accumulating a result.
dict.fold(scores, 0, fn(acc: Int, k: String, v: Int) -> acc + v)
pub fn find_keys(d: Dict(k, v), f: fn(k, v) -> Bool) -> List(k)Return all keys satisfying a predicate.
dict.find_keys(scores, fn(k: String, v: Int) -> v > 0)
pub fn update(d: Dict(k, v), key: k, f: fn(v) -> v, eq: fn(k, k) -> Bool) -> Dict(k, v)Update a key with a function. No-op if the key is not present.
dict.update(scores, "total", fn(n: Int) -> n + 1, fn(a: String, b: String) -> string.equal(a, b))
result
Result type and utilities for Donna.
Types
pub type Result(a, e)The Result type represents either success (Ok) or failure (Error).
Ok(a)Error(e)Functions
pub fn is_ok(res: Result(a, e)) -> BoolReturn True if the result is Ok.
result.is_ok(result.Ok(42))
pub fn is_error(res: Result(a, e)) -> BoolReturn True if the result is an Error.
result.is_error(result.Error("no"))
pub fn unwrap(res: Result(a, e), default: a) -> aUnwrap the Ok value, returning default if Error.
result.unwrap(result.Ok(42), 0)
pub fn unwrap_error(res: Result(a, e), default: e) -> eUnwrap the Error value, returning default if Ok.
result.unwrap_error(result.Error("no"), "")
pub fn map(res: Result(a, e), f: fn(a) -> b) -> Result(b, e)Apply f to the Ok value, leaving Error unchanged.
result.map(result.Ok(2), fn(n: Int) -> n * 2)
pub fn map_error(res: Result(a, e), f: fn(e) -> f) -> Result(a, f)Apply f to the Error value, leaving Ok unchanged.
result.map_error(result.Error("no"), fn(e: String) -> "error: " <> e)
pub fn then(res: Result(a, e), f: fn(a) -> Result(b, e)) -> Result(b, e)Chain: apply f which returns a Result, flattening the result.
result.then(result.Ok(2), fn(n: Int) -> result.Ok(n * 2))
pub fn or(res: Result(a, e), fallback: Result(a, e)) -> Result(a, e)Return first Ok, or the second result if the first is an Error.
result.or(result.Error("no"), result.Ok(42))
pub fn to_list(res: Result(a, e)) -> List(a)Convert Result to a list: Ok(x) -> [x], Error(_) -> [].
result.to_list(result.Ok(42))
files
File system utilities.
Functions
pub fn read(path: String) -> StringRead the entire contents of a file. Returns "" if the file does not exist.
files.read("README.md")
pub fn write(path: String, content: String) -> IntWrite content to a file, overwriting any existing content. Returns 0 on success, non-zero on error.
files.write("out.txt", "hello")
pub fn append(path: String, content: String) -> IntAppend content to a file. Returns 0 on success, non-zero on error.
files.append("out.txt", "\nagain")
pub fn exists(path: String) -> BoolReturn True if the path exists (file or directory).
files.exists("out.txt")
pub fn is_file(path: String) -> BoolReturn True if the path is a regular file.
files.is_file("out.txt")
pub fn is_dir(path: String) -> BoolReturn True if the path is a directory.
files.is_dir("src")
pub fn mkdir(path: String) -> IntCreate a directory. Returns 0 on success, non-zero on error.
files.mkdir("tmp")
pub fn delete(path: String) -> IntDelete a file. Returns 0 on success, non-zero on error.
files.delete("out.txt")
pub fn copy(src: String, dst: String) -> IntCopy a file from src to dst. Returns 0 on success, non-zero on error.
files.copy("in.txt", "out.txt")
pub fn list_dir(path: String) -> List(String)List the entries in a directory. Returns a list of entry names (not full paths).
files.list_dir("src")
pub fn join(a: String, b: String) -> StringJoin two path segments with a "/" separator.
files.join("src", "main.donna")
pub fn basename(path: String) -> StringReturn the final component of a path (the filename).
files.basename("src/main.donna")
pub fn dirname(path: String) -> StringReturn the directory component of a path (everything before the last "/"). Returns "." if there is no directory component.
files.dirname("src/main.donna")
pub fn extension(path: String) -> StringReturn the file extension including the dot (e.g. ".donna"), or "" if none.
files.extension("src/main.donna")
pub fn drop_extension(path: String) -> StringReturn the path with the extension removed.
files.drop_extension("src/main.donna")
option
Option type and utilities for Donna.
Types
pub type Option(a)The Option type represents a value that may or may not be present.
NoneSome(a)Functions
pub fn is_some(opt: Option(a)) -> BoolReturn True if the option contains a value.
option.is_some(option.Some(42))
pub fn is_none(opt: Option(a)) -> BoolReturn True if the option is empty.
option.is_none(option.None)
pub fn unwrap(opt: Option(a), default: a) -> aUnwrap the value, returning default if None.
option.unwrap(option.Some(42), 0)
pub fn map(opt: Option(a), f: fn(a) -> b) -> Option(b)Apply f to the contained value, or return None.
option.map(option.Some(2), fn(n: Int) -> n * 2)
pub fn then(opt: Option(a), f: fn(a) -> Option(b)) -> Option(b)Apply f which itself returns an Option, flattening the result.
option.then(option.Some(2), fn(n: Int) -> option.Some(n * 2))
pub fn or(opt: Option(a), fallback: Option(a)) -> Option(a)Return the first option if it has a value, otherwise return the second.
option.or(option.None, option.Some(42))
pub fn lazy_unwrap(opt: Option(a), f: fn() -> a) -> aReturn the value if Some, or call f to produce a default.
option.lazy_unwrap(option.None, fn() -> 42)
pub fn filter(opt: Option(a), f: fn(a) -> Bool) -> Option(a)Filter: return None if the predicate fails.
option.filter(option.Some(4), fn(n: Int) -> n > 0)
pub fn to_list(opt: Option(a)) -> List(a)Convert Option to a list of 0 or 1 elements.
option.to_list(option.Some(42))
bool
Boolean utilities for Donna.
Functions
pub fn not(b: Bool) -> BoolNegate a boolean value.
bool.not(False)
pub fn and(a: Bool, b: Bool) -> BoolLogical AND.
bool.and(True, False)
pub fn or(a: Bool, b: Bool) -> BoolLogical OR.
bool.or(True, False)
pub fn xor(a: Bool, b: Bool) -> BoolLogical XOR (exclusive or).
bool.xor(True, False)
pub fn to_int(b: Bool) -> IntConvert a bool to an integer: True -> 1, False -> 0.
bool.to_int(True)
pub fn to_string(b: Bool) -> StringConvert a bool to a string.
bool.to_string(False)
pub fn guard(b: Bool, then_val: a, else_val: a) -> aReturn a value based on a boolean condition.
bool.guard(True, "yes", "no")
float
Float utilities for Donna.
External functions
@external pub fn to_string(f: Float) -> StringConvert a float to its string representation.
float.to_string(3.14)
@external pub fn parse(s: String) -> FloatParse a float string. Invalid strings currently parse as 0.
float.parse("3.14")
@external pub fn min(a: Float, b: Float) -> FloatReturn the smaller of two floats.
float.min(1.0, 2.0)
@external pub fn max(a: Float, b: Float) -> FloatReturn the larger of two floats.
float.max(1.0, 2.0)
@external pub fn clamp(x: Float, lo: Float, hi: Float) -> FloatClamp a float between lower and upper bounds.
float.clamp(12.0, 0.0, 10.0)
@external pub fn is_positive(x: Float) -> BoolReturn True when the float is greater than zero.
float.is_positive(1.0)
@external pub fn is_negative(x: Float) -> BoolReturn True when the float is less than zero.
float.is_negative(-1.0)
@external pub fn is_zero(x: Float) -> BoolReturn True when the float is exactly zero.
float.is_zero(0.0)
@external pub fn sqrt(x: Float) -> FloatReturn the square root.
float.sqrt(9.0)
@external pub fn abs(x: Float) -> FloatReturn the absolute value.
float.abs(-3.0)
@external pub fn floor(x: Float) -> FloatRound downward to the nearest integer-valued float.
float.floor(3.8)
@external pub fn ceil(x: Float) -> FloatRound upward to the nearest integer-valued float.
float.ceil(3.2)
@external pub fn round(x: Float) -> FloatRound to the nearest integer-valued float.
float.round(3.5)
@external pub fn pow(base: Float, exp: Float) -> FloatRaise a base to an exponent.
float.pow(2.0, 8.0)
@external pub fn sin(x: Float) -> FloatReturn the sine of a value in radians.
float.sin(0.0)
@external pub fn cos(x: Float) -> FloatReturn the cosine of a value in radians.
float.cos(0.0)
@external pub fn tan(x: Float) -> FloatReturn the tangent of a value in radians.
float.tan(0.0)
@external pub fn log(x: Float) -> FloatReturn the natural logarithm.
float.log(10.0)
@external pub fn log2(x: Float) -> FloatReturn the base-2 logarithm.
float.log2(8.0)
@external pub fn log10(x: Float) -> FloatReturn the base-10 logarithm.
float.log10(100.0)
@external pub fn exp(x: Float) -> FloatReturn e raised to the given power.
float.exp(1.0)
int
Integer utilities for Donna.
Functions
pub fn parse(s: String) -> option.Option(Int)Parse a decimal integer string. Returns Some(n) on success. Note: uses atoi — always returns Some; invalid strings give 0.
int.parse("42")
pub fn to_string(n: Int) -> StringConvert an integer to its string representation.
int.to_string(42)
pub fn abs(n: Int) -> IntReturn the absolute value of an integer.
int.abs(-5)
pub fn min(a: Int, b: Int) -> IntReturn the minimum of two integers.
int.min(3, 7)
pub fn max(a: Int, b: Int) -> IntReturn the maximum of two integers.
int.max(3, 7)
pub fn clamp(n: Int, lo: Int, hi: Int) -> IntClamp a value between lo and hi (inclusive).
int.clamp(12, 0, 10)
pub fn is_even(n: Int) -> BoolCheck if an integer is even.
int.is_even(4)
pub fn is_odd(n: Int) -> BoolCheck if an integer is odd.
int.is_odd(3)
pub fn is_zero(n: Int) -> BoolCheck if an integer is zero.
int.is_zero(0)
pub fn is_positive(n: Int) -> BoolCheck if an integer is positive (> 0).
int.is_positive(4)
pub fn is_negative(n: Int) -> BoolCheck if an integer is negative (< 0).
int.is_negative(-4)
pub fn sign(n: Int) -> IntReturn the sign of an integer: -1, 0, or 1.
int.sign(-10)
pub fn pow(base: Int, exp: Int) -> IntCompute base raised to the exponent power (non-negative exponent).
int.pow(2, 8)
pub fn gcd(a: Int, b: Int) -> IntCompute greatest common divisor (Euclidean algorithm).
int.gcd(12, 8)
pub fn lcm(a: Int, b: Int) -> IntCompute least common multiple.
int.lcm(4, 6)
list
List utilities for Donna.
Functions
pub fn length(xs: List(a)) -> IntReturn the number of elements in a list.
list.length([1, 2, 3])
pub fn head(xs: List(a), default: a) -> aGet the first element of a list, or a default if empty.
list.head([1, 2, 3], 0)
pub fn tail(xs: List(a)) -> List(a)Get all elements after the first, or empty list if empty.
list.tail([1, 2, 3])
pub fn is_empty(xs: List(a)) -> BoolCheck if a list is empty.
list.is_empty([])
pub fn append(xs: List(a), ys: List(a)) -> List(a)Append two lists together.
list.append([1, 2], [3])
pub fn reverse(xs: List(a)) -> List(a)Reverse a list.
list.reverse([1, 2, 3])
pub fn sum(xs: List(Int)) -> IntSum a list of integers.
list.sum([1, 2, 3])
pub fn nth(xs: List(a), n: Int, default: a) -> aGet the nth element (0-indexed), or default if out of bounds.
list.nth([10, 20], 1, 0)
pub fn flatten(xs: List(List(a))) -> List(a)Flatten a list of lists.
list.flatten([[1, 2], [3]])
pub fn take(xs: List(a), n: Int) -> List(a)Take the first n elements.
list.take([1, 2, 3], 2)
pub fn drop(xs: List(a), n: Int) -> List(a)Drop the first n elements.
list.drop([1, 2, 3], 1)
pub fn repeat(val: a, n: Int) -> List(a)Create a list of n copies of a value.
list.repeat("x", 3)
pub fn range(start: Int, end: Int) -> List(Int)Create a list of integers from start to end (exclusive).
list.range(0, 3)
pub fn contains_int(xs: List(Int), val: Int) -> BoolCheck if a list contains an integer value.
list.contains_int([1, 2, 3], 2)
pub fn contains_str(xs: List(String), val: String) -> BoolCheck if a list contains a string value.
list.contains_str(["a", "b"], "b")
pub fn zip_length(xs: List(a)) -> IntZip two lists into a list of pairs (as 2-tuples).
list.zip_length(["a", "b"])
pub fn minimum(xs: List(Int), default: Int) -> IntGet the minimum of a list of integers (or default if empty).
list.minimum([3, 1, 4], 0)
pub fn maximum(xs: List(Int), default: Int) -> IntGet the maximum of a list of integers (or default if empty).
list.maximum([3, 1, 4], 0)
pub fn is_sorted(xs: List(Int)) -> BoolCheck if a list of integers is sorted in ascending order.
list.is_sorted([1, 2, 3])
pub fn map(xs: List(a), f: fn(a) -> b) -> List(b)Apply a function to every element, returning a new list.
list.map([1, 2, 3], fn(n: Int) -> n * 2)
pub fn filter(xs: List(a), f: fn(a) -> Bool) -> List(a)Keep only elements for which the predicate returns True.
list.filter([1, 2, 3], fn(n: Int) -> n > 1)
pub fn fold(xs: List(a), init: b, f: fn(b, a) -> b) -> bFold left: combine elements with an accumulator.
list.fold([1, 2, 3], 0, fn(acc: Int, n: Int) -> acc + n)
pub fn fold_right(xs: List(a), init: b, f: fn(a, b) -> b) -> bFold right: combine elements right-to-left.
list.fold_right([1, 2, 3], 0, fn(n: Int, acc: Int) -> n + acc)
pub fn any(xs: List(a), f: fn(a) -> Bool) -> BoolCheck if any element satisfies the predicate.
list.any([1, 2, 3], fn(n: Int) -> n > 2)
pub fn all(xs: List(a), f: fn(a) -> Bool) -> BoolCheck if all elements satisfy the predicate.
list.all([2, 4], fn(n: Int) -> n % 2 == 0)
pub fn find(xs: List(a), f: fn(a) -> Bool, default: a) -> aFind the first element satisfying the predicate, or default if none.
list.find([1, 2, 3], fn(n: Int) -> n > 1, 0)
pub fn flat_map(xs: List(a), f: fn(a) -> List(b)) -> List(b)Flat-map: apply f to each element and concatenate the results.
list.flat_map([1, 2], fn(n: Int) -> [n, n])
pub fn count(xs: List(a), f: fn(a) -> Bool) -> IntCount elements satisfying the predicate.
list.count([1, 2, 3], fn(n: Int) -> n > 1)
pub fn zip_with(xs: List(a), ys: List(b), f: fn(a, b) -> c) -> List(c)Zip two lists, applying f to corresponding pairs.
list.zip_with([1, 2], [3, 4], fn(a: Int, b: Int) -> a + b)
pub fn each(xs: List(a), f: fn(a) -> Nil) -> NilEach: apply a function for its side effects.
list.each(["a", "b"], fn(s: String) -> echo s)
string
String utilities for Donna.
Functions
pub fn length(s: String) -> IntReturn the number of bytes in a string.
string.length("Donna")
pub fn concat(a: String, b: String) -> StringConcatenate two strings.
string.concat("Don", "na")
pub fn equal(a: String, b: String) -> BoolCheck if two strings are equal.
string.equal("a", "a")
pub fn is_empty(s: String) -> BoolCheck if a string is empty.
string.is_empty("")
pub fn char_at(s: String, i: Int) -> IntGet the byte value of the character at position i.
string.char_at("Donna", 0)
pub fn char_str(s: String, i: Int) -> StringGet the character (as a 1-byte String) at position i.
string.char_str("Donna", 0)
pub fn slice(s: String, pos: Int, len: Int) -> StringGet a substring starting at pos with given length.
string.slice("Donna", 1, 3)
pub fn starts_with(s: String, prefix: String) -> BoolCheck if string starts with a given prefix.
string.starts_with("Donna", "Don")
pub fn ends_with(s: String, suffix: String) -> BoolCheck if string ends with a given suffix.
string.ends_with("Donna", "na")
pub fn from_int(n: Int) -> StringConvert an Int to its string representation.
string.from_int(42)
pub fn repeat(s: String, n: Int) -> StringRepeat a string n times.
string.repeat("ha", 3)
pub fn reverse(s: String) -> StringReverse a string (byte-by-byte).
string.reverse("abc")
pub fn contains(s: String, sub: String) -> BoolReturn True if s contains sub as a substring.
string.contains("hello Donna", "Donna")
pub fn index_of(s: String, sub: String) -> IntReturn the index of the first occurrence of sub in s, or -1 if not found.
string.index_of("hello Donna", "Donna")
pub fn index_of_from(s: String, sub: String, from: Int) -> IntReturn the index of sub in s at or after from, or -1 if not found.
string.index_of_from("abcabc", "abc", 1)
pub fn split(s: String, sep: String) -> List(String)Split a string by a separator. Returns list of parts.
string.split("a,b,c", ",")
pub fn trim_start(s: String) -> StringRemove leading whitespace (space, tab, carriage return, newline).
string.trim_start(" Donna")
pub fn trim_end(s: String) -> StringRemove trailing whitespace.
string.trim_end("Donna ")
pub fn trim(s: String) -> StringRemove leading and trailing whitespace.
string.trim(" Donna ")
pub fn replace(s: String, from: String, to: String) -> StringReplace all occurrences of from with to in s.
string.replace("hello world", "world", "Donna")
pub fn join(parts: List(String), sep: String) -> StringJoin a list of strings with a separator between each element.
string.join(["a", "b"], ",")
pub fn pad_left(s: String, width: Int, ch: String) -> StringPad a string on the left to at least width characters using ch.
string.pad_left("42", 5, "0")
pub fn is_digits(s: String) -> BoolReturn True if the string contains only digits (ASCII 0-9).
string.is_digits("123")
pub fn to_int(s: String) -> IntParse a string as an integer. Returns 0 if the string is not a valid integer.
string.to_int("42")
pub fn lowercase(s: String) -> StringConvert all ASCII uppercase letters in a string to lowercase.
string.lowercase("DONNA")
pub fn to_slug(s: String) -> StringConvert a string to a URL-friendly slug: lowercase, spaces become hyphens, non-alphanumeric characters (except hyphens) are dropped.
string.to_slug("Hello Donna!")
External functions
@external pub fn char_from_code(n: Int) -> StringCreate a 1-byte string from a character code (byte value).
string.char_from_code(65)
shell
Shell execution utilities.
Functions
pub fn getenv(name: String) -> StringGet the value of an environment variable. Returns "" if not set.
shell.getenv("HOME")
pub fn flush() -> IntFlush stdout — ensures all buffered output is written before exec.
shell.flush()
pub fn run(cmd: String) -> IntRun a raw shell command string. Returns the exit code.
shell.run("true")
pub fn capture(cmd: String) -> StringCapture the stdout of a raw shell command. Returns the output as a string.
shell.capture("printf hello")
pub fn exec(cmd: String, args: List(String)) -> IntExecute a command with a list of arguments. Returns the exit code.
shell.exec("printf", ["hello"])
pub fn output(cmd: String, args: List(String)) -> StringCapture the stdout of a command with a list of arguments.
shell.output("printf", ["hello"])
pub fn output_with_err(cmd: String, args: List(String)) -> StringCapture the stdout and stderr of a command with a list of arguments.
shell.output_with_err("sh", ["-c", "echo err >&2"])
pub fn exec_in(cmd: String, args: List(String), dir: String) -> IntExecute a command in a specific working directory. Returns the exit code.
shell.exec_in("pwd", [], "/tmp")