code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(4.9K lines)

% API

Builtins

USE_COLOR

USE_COLOR : Bool

Whether or not the console prefers ANSI color escape sequences in the output.

ask

ask : func(prompt: Text, bold: Bool = yes, force_tty: Bool = yes -> Text?)

Gets a line of user input text with a prompt.

When a program is receiving input from a pipe or writing its output to a pipe, this flag (which is enabled by default) forces the program to write the prompt to /dev/tty and read the input from /dev/tty, which circumvents the pipe. This means that foo | ./tomo your-program | baz will still show a visible prompt and read user input, despite the pipes. Setting this flag to no will mean that the prompt is written to stdout and input is read from stdin, even if those are pipes.

Argument Type Description Default
prompt Text The text to print as a prompt before getting the input. -
bold Bool Whether or not to print make the prompt appear bold on a console. yes
force_tty Bool Whether or not to force the use of /dev/tty. yes

Return: A line of user input text without a trailing newline, or empty text if something went wrong (e.g. the user hit Ctrl-D).

Example:

assert ask("What's your name? ") == "Arthur Dent"

at_cleanup

at_cleanup : func(fn: func() -> Void)

Register a function that runs at cleanup time for Tomo programs. Cleanup time happens when a program exits (see atexit() in C), or immediately before printing error messages in a call to fail(). This allows for terminal cleanup so error messages can be visible as the program shuts down.

Use this API very carefully, because errors that occur during cleanup functions may make it extremely hard to figure out what's going on. Cleanup functions should be designed to not error under any circumstances.

Argument Type Description Default
fn func() A function to run at cleanup time. -

Return: Nothing.

Example:

at_cleanup(func()
    _ := (/tmp/file.txt).remove(ignore_missing=yes)
)

exit

exit : func(message: Text? = none, status: Int32 = Int32(1) -> Abort)

Exits the program with a given status and optionally prints a message.

Argument Type Description Default
message Text? If nonempty, this message will be printed (with a newline) before exiting. none
status Int32 The status code that the program with exit with. Int32(1)

Return: This function never returns.

Example:

exit("Goodbye forever!", Int32(1))

fail

fail : func(message: Text -> Abort)

Prints a message to the console, aborts the program, and prints a stack trace.

Argument Type Description Default
message Text The error message to print. -

Return: Nothing, aborts the program.

Example:

fail("Oh no!")

getenv

getenv : func(name: Text -> Text?)

Gets an environment variable.

Argument Type Description Default
name Text The name of the environment variable to get. -

Return: If set, the environment variable's value, otherwise, none.

Example:

assert getenv("TERM") == "xterm-256color"
assert getenv("not_a_variable") == none

print

print : func(text: Text, newline: Bool = yes -> Void)

Prints a message to the console (alias for say()).

Argument Type Description Default
text Text The text to print. -
newline Bool Whether or not to print a newline after the text. yes

Return: Nothing.

Example:

print("Hello ", newline=no)
print("world!")

say

say : func(text: Text, newline: Bool = yes -> Void)

Prints a message to the console.

Argument Type Description Default
text Text The text to print. -
newline Bool Whether or not to print a newline after the text. yes

Return: Nothing.

Example:

say("Hello ", newline=no)
say("world!")

setenv

setenv : func(name: Text, value: Text? -> Void)

Sets an environment variable.

Argument Type Description Default
name Text The name of the environment variable to set. -
value Text? The new value of the environment variable. If none, then the environment variable will be unset. -

Return: Nothing.

Example:

setenv("FOOBAR", "xyz")

sleep

sleep : func(seconds: Num -> Void)

Pause execution for a given number of seconds.

Argument Type Description Default
seconds Num How many seconds to sleep for. -

Return: Nothing.

Example:

sleep(1.5)

Bool

Bool.parse

Bool.parse : func(text: Text, remainder: &Text? = none -> Bool?)

Converts a text representation of a boolean value into a boolean. Acceptable boolean values are case-insensitive variations of yes/no, y/n, true/false, on/off.

Argument Type Description Default
text Text The string containing the boolean value. -
remainder &Text? If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. none

Return: yes if the string matches a recognized truthy boolean value; otherwise return no.

Example:

assert Bool.parse("yes") == yes
assert Bool.parse("no") == no
assert Bool.parse("???") == none

assert Bool.parse("yesJUNK") == none
remainder : Text
assert Bool.parse("yesJUNK", &remainder) == yes
assert remainder == "JUNK"

Byte

Byte.get_bit

Byte.get_bit : func(i: Byte, bit_index: Int -> Bool)

In the binary representation of a byte, check whether a given bit index is set to 1 or not.

The bit index must be between 1-8 or a runtime error will be produced.

Argument Type Description Default
i Byte The byte whose bits are being inspected. -
bit_index Int The index of the bit to check (1-indexed, range 1-8). -

Return: Whether or not the given bit index is set to 1 in the byte.

Example:

assert Byte(6).get_bit(1) == no
assert Byte(6).get_bit(2) == yes
assert Byte(6).get_bit(3) == yes
assert Byte(6).get_bit(4) == no

Byte.hex

Byte.hex : func(byte: Byte, uppercase: Bool = yes, prefix: Bool = no -> Text)

Convert a byte to a hexidecimal text representation.

Argument Type Description Default
byte Byte The byte to convert to hex. -
uppercase Bool Whether or not to use uppercase hexidecimal letters. yes
prefix Bool Whether or not to prepend a 0x prefix. no

Return: The byte as a hexidecimal text.

Example:

assert Byte(18).hex(prefix=yes) == "0x12"

Byte.is_between

Byte.is_between : func(x: Byte, low: Byte, high: Byte -> Bool)

Determines if an integer is between two numbers (inclusive).

Argument Type Description Default
x Byte The integer to be checked. -
low Byte One end of the range to check (inclusive); -
high Byte The other end of the range to check (inclusive); -

Return: yes if a <= x and x <= b or b <= x and x <= a, otherwise no

Example:

assert Byte(7).is_between(1, 10) == yes
assert Byte(7).is_between(10, 1) == yes
assert Byte(7).is_between(100, 200) == no
assert Byte(7).is_between(1, 7) == yes

Byte.parse

Byte.parse : func(text: Text, base: Int? = none, remainder: &Text? = none -> Byte?)

Parse a byte literal from text.

Argument Type Description Default
text Text The text to parse. -
base Int? The numeric base to use when parsing the byte. If unspecified, the byte's base will be inferred from the text prefix. After any "+" or "-" sign, if the text begins with "0x", the base will be assumed to be 16, "0o" will assume base 8, "0b" will assume base 2, otherwise the base will be assumed to be 10. none
remainder &Text? If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. none

Return: The byte parsed from the text, if successful, otherwise none.

Example:

assert Byte.parse("5") == Byte(5)
assert Byte.parse("asdf") == none
assert Byte.parse("123xyz") == none

remainder : Text
assert Byte.parse("123xyz", remainder=&remainder) == Byte(123)
assert remainder == "xyz"

Byte.to

Byte.to : func(first: Byte, last: Byte, step: Int8? = none -> func(->Byte?))

Returns an iterator function that iterates over the range of bytes specified.

Argument Type Description Default
first Byte The starting value of the range. -
last Byte The ending value of the range. -
step Int8? An optional step size to use. If unspecified or none, the step will be inferred to be +1 if last >= first, otherwise -1. none

Return: An iterator function that returns each byte in the given range (inclusive).

Example:

iter := Byte(2).to(4)
assert iter() == Byte(2)
assert iter() == Byte(3)
assert iter() == Byte(4)
assert iter() == none

assert [x for x in Byte(2).to(5)] == [Byte(2), Byte(3), Byte(4), Byte(5)]
assert [x for x in Byte(5).to(2)] == [Byte(5), Byte(4), Byte(3), Byte(2)]
assert [x for x in Byte(2).to(5, step=2)] == [Byte(2), Byte(4)]

CString

CString.as_text

CString.as_text : func(str: CString -> Text)

Convert a C string to Text.

Argument Type Description Default
str CString The C string. -

Return: The C string as a Text.

Example:

assert CString("Hello").as_text() == "Hello"

CString.join

CString.join : func(glue: CString, pieces: [CString] -> CString)

Join a list of C strings together with a separator.

Argument Type Description Default
glue CString The C joiner used to between elements. -
pieces [CString] A list of C strings to join. -

Return: A C string of the joined together bits.

Example:

assert CString(",").join([CString("a"), CString("b")]) == CString("a,b")

Int

Int.abs

Int.abs : func(x: Int -> Int)

Calculates the absolute value of an integer.

Argument Type Description Default
x Int The integer whose absolute value is to be calculated. -

Return: The absolute value of x.

Example:

assert (-10).abs() == 10

Int.choose

Int.choose : func(n: Int, k: Int -> Int)

Computes the binomial coefficient of the given numbers (the equivalent of n choose k in combinatorics). This is equal to n.factorial()/(k.factorial() * (n-k).factorial()).

Argument Type Description Default
n Int The number of things to choose from. -
k Int The number of things to be chosen. -

Return: The binomial coefficient, equivalent to the number of ways to uniquely choose k objects from among n objects, ignoring order.

Example:

assert 4.choose(2) == 6

Int.clamped

Int.clamped : func(x: Int, low: Int, high: Int -> Int)

Returns the given number clamped between two values so that it is within that range.

Argument Type Description Default
x Int The integer to clamp. -
low Int The lowest value the result can take. -
high Int The highest value the result can take. -

Return: The first argument clamped between the other two arguments.

Example:

assert 2.clamped(5, 10) == 5

Int.factorial

Int.factorial : func(n: Int -> Text)

Computes the factorial of an integer.

Argument Type Description Default
n Int The integer to compute the factorial of. -

Return: The factorial of the given integer.

Example:

assert 10.factorial() == 3628800

Int.get_bit

Int.get_bit : func(i: Int, bit_index: Int -> Bool)

In the binary representation of an integer, check whether a given bit index is set to 1 or not.

For fixed-size integers, the bit index must be between 1 and the number of bits in that integer (i.e. 1-64 for Int64). For Int, the bit index must be between 1 and Int64.max. Values outside this range will produce a runtime error.

Argument Type Description Default
i Int The integer whose bits are being inspected. -
bit_index Int The index of the bit to check (1-indexed). -

Return: Whether or not the given bit index is set to 1 in the binary representation of the integer.

Example:

assert 6.get_bit(1) == no
assert 6.get_bit(2) == yes
assert 6.get_bit(3) == yes
assert 6.get_bit(4) == no

Int.hex

Int.hex : func(i: Int, digits: Int = 0, uppercase: Bool = yes, prefix: Bool = yes -> Text)

Converts an integer to its hexadecimal representation.

Argument Type Description Default
i Int The integer to be converted. -
digits Int The minimum number of digits in the output string. 0
uppercase Bool Whether to use uppercase letters for hexadecimal digits. yes
prefix Bool Whether to include a "0x" prefix. yes

Return: The hexadecimal string representation of the integer.

Example:

assert 255.hex(digits=4, uppercase=yes, prefix=yes) == "0x00FF"

Int.is_between

Int.is_between : func(x: Int, a: Int, b: Int -> Bool)

Determines if an integer is between two numbers (inclusive).

Argument Type Description Default
x Int The integer to be checked. -
a Int One end of the range to check (inclusive). -
b Int The other end of the range to check (inclusive). -

Return: yes if a <= x and x <= b or a >= x and x >= b, otherwise no

Example:

assert 7.is_between(1, 10) == yes
assert 7.is_between(10, 1) == yes
assert 7.is_between(100, 200) == no
assert 7.is_between(1, 7) == yes

Int.is_prime

Int.is_prime : func(x: Int, reps: Int = 50 -> Bool)

Determines if an integer is a prime number.

This function is probabilistic. With the default arguments, the chances of getting an incorrect answer are astronomically small (on the order of 10^(-30)). See the GNU MP docs for more details.

Argument Type Description Default
x Int The integer to be checked. -
reps Int The number of repetitions for primality tests. 50

Return: yes if x is a prime number, no otherwise.

Example:

assert 7.is_prime() == yes
assert 6.is_prime() == no

Int.next_prime

Int.next_prime : func(x: Int -> Int)

Finds the next prime number greater than the given integer.

This function is probabilistic, but the chances of getting an incorrect answer are astronomically small (on the order of 10^(-30)). See the GNU MP docs for more details.

Argument Type Description Default
x Int The integer after which to find the next prime. -

Return: The next prime number greater than x.

Example:

assert 11.next_prime() == 13

Int.octal

Int.octal : func(i: Int, digits: Int = 0, prefix: Bool = yes -> Text)

Converts an integer to its octal representation.

Argument Type Description Default
i Int The integer to be converted. -
digits Int The minimum number of digits in the output string. 0
prefix Bool Whether to include a "0o" prefix. yes

Return: The octal string representation of the integer.

Example:

assert 64.octal(digits=4, prefix=yes) == "0o0100"

Int.onward

Int.onward : func(first: Int, step: Int = 1 -> Text)

Return an iterator that counts infinitely from the starting integer (with an optional step size).

Argument Type Description Default
first Int The starting integer. -
step Int The increment step size. 1

Return: An iterator function that counts onward from the starting integer.

Example:

nums : &[Int] = &[]
for i in 5.onward()
    nums.insert(i)
    stop if i == 10
assert nums[] == [5, 6, 7, 8, 9, 10]

Int.parse

Int.parse : func(text: Text, base: Int? = none, remainder: &Text? = none -> Int?)

Converts a text representation of an integer into an integer.

Argument Type Description Default
text Text The text containing the integer. -
base Int? The numeric base to use when parsing the integer. If unspecified, the integer's base will be inferred from the text prefix. After any "+" or "-" sign, if the text begins with "0x", the base will be assumed to be 16, "0o" will assume base 8, "0b" will assume base 2, otherwise the base will be assumed to be 10. none
remainder &Text? If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. none

Return: The integer represented by the text. If the given text contains a value outside of the representable range or if the entire text can't be parsed as an integer, none will be returned.

Example:

assert Int.parse("123") == 123
assert Int.parse("0xFF") == 255
assert Int.parse("123xyz") == none
remainder : Text
assert Int.parse("123xyz", remainder=&remainder) == 123
assert remainder == "xyz"

# Can't parse:
assert Int.parse("asdf") == none

# Outside valid range:
assert Int8.parse("9999999") == none

# Explicitly specifying base:
assert Int.parse("10", base=16) == 16

Int.sqrt

Int.sqrt : func(x: Int -> Int)

Calculates the nearest square root of an integer.

Argument Type Description Default
x Int The integer whose square root is to be calculated. -

Return: The integer part of the square root of x.

Example:

assert 16.sqrt() == 4
assert 17.sqrt() == 4

Int.to

Int.to : func(first: Int, last: Int, step: Int? = none -> func(->Int?))

Returns an iterator function that iterates over the range of numbers specified.

Argument Type Description Default
first Int The starting value of the range. -
last Int The ending value of the range. -
step Int? An optional step size to use. If unspecified or none, the step will be inferred to be +1 if last >= first, otherwise -1. none

Return: An iterator function that returns each integer in the given range (inclusive).

Example:

iter := 2.to(5)
assert iter() == 2
assert iter() == 3
assert iter() == 4
assert iter() == 5
assert iter() == none

assert [x for x in 2.to(5)] == [2, 3, 4, 5]
assert [x for x in 5.to(2)] == [5, 4, 3, 2]
assert [x for x in 2.to(5, step=2)] == [2, 4]

List

List.binary_search

List.binary_search : func(list: [T], by: func(x,y:&T->Int32) = T.compare -> Int)

Performs a binary search on a sorted list.

Argument Type Description Default
list [T] The sorted list to search. -
by func(x,y:&T->Int32) The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. T.compare

Return: Assuming the input list is sorted according to the given comparison function, return the index where the given item would be inserted to maintain the sorted order. That is, if the item is found, return its index, otherwise return the place where it would be found if it were inserted and the list were sorted.

Example:

assert [1, 3, 5, 7, 9].binary_search(5) == 3
assert [1, 3, 5, 7, 9].binary_search(-999) == 1
assert [1, 3, 5, 7, 9].binary_search(999) == 6

List.by

List.by : func(list: [T], step: Int -> [T])

Creates a new list with elements spaced by the specified step value.

Argument Type Description Default
list [T] The original list. -
step Int The step value for selecting elements. -

Return: A new list with every step-th element from the original list.

Example:

assert [1, 2, 3, 4, 5, 6].by(2) == [1, 3, 5]

List.clear

List.clear : func(list: @[T] -> Void)

Clears all elements from the list.

Argument Type Description Default
list @[T] The mutable reference to the list to be cleared. -

Return: Nothing.

Example:

list := &[10, 20]
list.clear()
assert list[] == []

List.counts

List.counts : func(list: [T] -> {T=Int})

Counts the occurrences of each element in the list.

Argument Type Description Default
list [T] The list to count elements in. -

Return: A table mapping each element to its count.

Example:

assert [10, 20, 30, 30, 30].counts() == {10:1, 20:1, 30:3}

List.find

List.find : func(list: [T], target: T -> Int?)

Finds the index of the first occurrence of an element (if any).

Argument Type Description Default
list [T] The list to search through. -
target T The item to search for. -

Return: The index of the first occurrence or none if not found.

Example:

assert [10, 20, 30, 40, 50].find(20) == 2
assert [10, 20, 30, 40, 50].find(9999) == none

List.from

List.from : func(list: [T], first: Int -> [T])

Returns a slice of the list starting from a specified index.

Argument Type Description Default
list [T] The original list. -
first Int The index to start from. -

Return: A new list starting from the specified index.

Example:

assert [10, 20, 30, 40, 50].from(3) == [30, 40, 50]

List.has

List.has : func(list: [T], target: T -> Bool)

Checks if the list has an element.

Argument Type Description Default
list [T] The list to check. -
target T The element to check for. -

Return: yes if the list has the element, no otherwise.

Example:

assert [10, 20, 30].has(20) == yes

List.heap_pop

List.heap_pop : func(list: @[T], by: func(x,y:&T->Int32) = T.compare -> T?)

Removes and returns the top element of a heap or none if the list is empty. By default, this is the minimum value in the heap.

Argument Type Description Default
list @[T] The mutable reference to the heap. -
by func(x,y:&T->Int32) The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. T.compare

Return: The removed top element of the heap or none if the list is empty.

Example:

my_heap := &[30, 10, 20]
my_heap.heapify()
assert my_heap.heap_pop() == 10

List.heap_push

List.heap_push : func(list: @[T], item: T, by = T.compare -> Void)

Adds an element to the heap and maintains the heap property. By default, this is a minimum heap.

Argument Type Description Default
list @[T] The mutable reference to the heap. -
item T The item to be added. -
by `` The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. T.compare

Return: Nothing.

Example:

my_heap : &[Int]
my_heap.heap_push(10)
assert my_heap.heap_pop() == 10

List.heapify

List.heapify : func(list: @[T], by: func(x,y:&T->Int32) = T.compare -> Void)

Converts a list into a heap.

Argument Type Description Default
list @[T] The mutable reference to the list to be heapified. -
by func(x,y:&T->Int32) The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. T.compare

Return: Nothing.

Example:

my_heap := &[30, 10, 20]
my_heap.heapify()

List.insert

List.insert : func(list: @[T], item: T, at: Int = 0 -> Void)

Inserts an element at a specified position in the list.

Since indices are 1-indexed and negative indices mean "starting from the back", an index of 0 means "after the last item".

Argument Type Description Default
list @[T] The mutable reference to the list. -
item T The item to be inserted. -
at Int The index at which to insert the item. 0

Return: Nothing.

Example:

list := &[10, 20]
list.insert(30)
assert list == [10, 20, 30]

list.insert(999, at=2)
assert list == [10, 999, 20, 30]

List.insert_all

List.insert_all : func(list: @[T], items: [T], at: Int = 0 -> Void)

Inserts a list of items at a specified position in the list.

Since indices are 1-indexed and negative indices mean "starting from the back", an index of 0 means "after the last item".

Argument Type Description Default
list @[T] The mutable reference to the list. -
items [T] The items to be inserted. -
at Int The index at which to insert the item. 0

Return: Nothing.

Example:

list := &[10, 20]
list.insert_all([30, 40])
assert list == [10, 20, 30, 40]

list.insert_all([99, 100], at=2)
assert list == [10, 99, 100, 20, 30, 40]

List.pop

List.pop : func(list: &[T], index: Int = -1 -> T?)

Removes and returns an item from the list. If the given index is present in the list, the item at that index will be removed and the list will become one element shorter.

Since negative indices are counted from the back, the default behavior is to pop the last value.

Argument Type Description Default
list &[T] The list to remove an item from. -
index Int The index from which to remove the item. -1

Return: none if the list is empty or the given index does not exist in the list, otherwise the item at the given index.

Example:

list := &[10, 20, 30, 40]

assert list.pop() == 40
assert list[] == [10, 20, 30]

assert list.pop(index=2) == 20
assert list[] == [10, 30]

List.random

List.random : func(list: [T], random: func(min,max:Int64->Int64)? = none -> T?)

Selects a random element from the list.

Argument Type Description Default
list [T] The list from which to select a random element. -
random func(min,max:Int64->Int64)? If provided, this function will be used to get a random index in the list. Returned values must be between min and max (inclusive). (Used for deterministic pseudorandom number generation) none

Return: A random element from the list or none if the list is empty.

Example:

nums := [10, 20, 30]
pick := nums.random()!
assert nums.has(pick)
empty : [Int]
assert empty.random() == none

List.remove_at

List.remove_at : func(list: @[T], at: Int = -1, count: Int = 1 -> Void)

Removes elements from the list starting at a specified index.

Since negative indices are counted from the back, the default behavior is to remove the last item.

Argument Type Description Default
list @[T] The mutable reference to the list. -
at Int The index at which to start removing elements. -1
count Int The number of elements to remove. 1

Return: Nothing.

Example:

list := &[10, 20, 30, 40, 50]
list.remove_at(2)
assert list == [10, 30, 40, 50]

list.remove_at(2, count=2)
assert list == [10, 50]

List.remove_item

List.remove_item : func(list: @[T], item: T, max_count: Int = -1 -> Void)

Removes all occurrences of a specified item from the list.

A negative max_count means "remove all occurrences".

Argument Type Description Default
list @[T] The mutable reference to the list. -
item T The item to be removed. -
max_count Int The maximum number of occurrences to remove. -1

Return: Nothing.

Example:

list := &[10, 20, 10, 20, 30]
list.remove_item(10)
assert list == [20, 20, 30]

list.remove_item(20, max_count=1)
assert list == [20, 30]

List.reversed

List.reversed : func(list: [T] -> [T])

Returns a reversed slice of the list.

Argument Type Description Default
list [T] The list to be reversed. -

Return: A slice of the list with elements in reverse order.

Example:

assert [10, 20, 30].reversed() == [30, 20, 10]

List.sample

List.sample : func(list: [T], count: Int, weights: [Num]? = none, random: func(->Num)? = none -> [T])

Selects a sample of elements from the list, optionally with weighted probabilities.

Errors will be raised if any of the following conditions occurs: - The given list has no elements and count >= 1 - count < 0 (negative count) - The number of weights provided doesn't match the length of the list. - Any weight in the weights list is negative, infinite, or NaN - The sum of the given weights is zero (zero probability for every element).

Argument Type Description Default
list [T] The list to sample from. -
count Int The number of elements to sample. -
weights [Num]? The probability weights for each element in the list. These values do not need to add up to any particular number, they are relative weights. If no weights are given, elements will be sampled with uniform probability. none
random func(->Num)? If provided, this function will be used to get random values for sampling the list. The provided function should return random numbers between 0.0 (inclusive) and 1.0 (exclusive). (Used for deterministic pseudorandom number generation) none

Return: A list of sampled elements from the list.

Example:

_ := [10, 20, 30].sample(2, weights=[90%, 5%, 5%]) # E.g. [10, 10]

List.shuffle

List.shuffle : func(list: @[T], random: func(min,max:Int64->Int64)? = none -> Void)

Shuffles the elements of the list in place.

Argument Type Description Default
list @[T] The mutable reference to the list to be shuffled. -
random func(min,max:Int64->Int64)? If provided, this function will be used to get a random index in the list. Returned values must be between min and max (inclusive). (Used for deterministic pseudorandom number generation) none

Return: Nothing.

Example:

nums := &[10, 20, 30, 40]
nums.shuffle()
# E.g. [20, 40, 10, 30]

List.shuffled

List.shuffled : func(list: [T], random: func(min,max:Int64->Int64)? = none -> [T])

Creates a new list with elements shuffled.

Argument Type Description Default
list [T] The list to be shuffled. -
random func(min,max:Int64->Int64)? If provided, this function will be used to get a random index in the list. Returned values must be between min and max (inclusive). (Used for deterministic pseudorandom number generation) none

Return: A new list with shuffled elements.

Example:

nums := [10, 20, 30, 40]
_ := nums.shuffled()
# E.g. [20, 40, 10, 30]

List.slice

List.slice : func(list: [T], from: Int, to: Int -> [T])

Returns a slice of the list spanning the given indices (inclusive).

Argument Type Description Default
list [T] The original list. -
from Int The first index to include. -
to Int The last index to include. -

Return: A new list spanning the given indices. Note: negative indices are counted from the back of the list, so -1 refers to the last element, -2 the second-to-last, and so on.

Example:

assert [10, 20, 30, 40, 50].slice(2, 4) == [20, 30, 40]
assert [10, 20, 30, 40, 50].slice(-3, -2) == [30, 40]

List.sort

List.sort : func(list: @[T], by = T.compare -> Void)

Sorts the elements of the list in place in ascending order (small to large).

Argument Type Description Default
list @[T] The mutable reference to the list to be sorted. -
by `` The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. T.compare

Return: Nothing.

Example:

list := &[40, 10, -30, 20]
list.sort()
assert list == [-30, 10, 20, 40]

list.sort(func(a,b:&Int) a.abs() <> b.abs())
assert list == [10, 20, -30, 40]

List.sorted

List.sorted : func(list: [T], by = T.compare -> [T])

Creates a new list with elements sorted.

Argument Type Description Default
list [T] The list to be sorted. -
by `` The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. T.compare

Return: A new list with sorted elements.

Example:

assert [40, 10, -30, 20].sorted() == [-30, 10, 20, 40]
assert [40, 10, -30, 20].sorted(
   func(a,b:&Int) a.abs() <> b.abs()
) == [10, 20, -30, 40]

List.to

List.to : func(list: [T], last: Int -> [T])

Returns a slice of the list from the start of the original list up to a specified index (inclusive).

Argument Type Description Default
list [T] The original list. -
last Int The index up to which elements should be included. -

Return: A new list containing elements from the start up to the specified index.

Example:

assert [10, 20, 30, 40, 50].to(3) == [10, 20, 30]
assert [10, 20, 30, 40, 50].to(-2) == [10, 20, 30, 40]

List.unique

List.unique : func(list: [T] -> {T})

Returns a set of the unique elements of the list.

Argument Type Description Default
list [T] The list to process. -

Return: A set of the unique elements from the list.

Example:

assert [10, 20, 10, 10, 30].unique() == {10, 20, 30}

List.where

List.where : func(list: [T], predicate: func(item:&T -> Bool) -> Int)

Find the index of the first item that matches a predicate function (if any).

Argument Type Description Default
list [T] The list to search through. -
predicate func(item:&T -> Bool) A function that returns yes if the item's index should be returned or no if it should not. -

Return: Returns the index of the first item where the predicate is true or none if no item matches.

Example:

assert ["BC", "ABC", "CD"].where(func(t:&Text) t.starts_with("A")) == 2
assert ["BC", "ABC", "CD"].where(func(t:&Text) t.starts_with("X")) == none

Num

Num.1_PI

Num.1_PI : Num

The constant $\frac{1}{\pi}$.

Num.2_PI

Num.2_PI : Num

The constant $2 \times \pi$.

Num.2_SQRTPI

Num.2_SQRTPI : Num

The constant $2 \times \sqrt{\pi}$.

Num.E

Num.E : Num

The base of the natural logarithm ($e$).

Num.INF

Num.INF : Num

Positive infinity.

Num.LN10

Num.LN10 : Num

The natural logarithm of 10.

Num.LN2

Num.LN2 : Num

The natural logarithm of 2.

Num.LOG2E

Num.LOG2E : Num

The base 2 logarithm of $e$

Num.PI

Num.PI : Num

Pi ($\pi$).

Num.PI_2

Num.PI_2 : Num

$\frac{\pi}{2}$

Num.PI_4

Num.PI_4 : Num

$\frac{\pi}{4}$

Num.SQRT1_2

Num.SQRT1_2 : Num

$\sqrt{\frac{1}{2}}$

Num.SQRT2

Num.SQRT2 : Num

$\sqrt{2}$

Num.TAU

Num.TAU : Num

Tau ($2 \times \pi$)

Num.abs

Num.abs : func(n: Num -> Num)

Calculates the absolute value of a number.

Argument Type Description Default
n Num The number whose absolute value is to be computed. -

Return: The absolute value of n.

Example:

assert (-3.5).abs() == 3.5

Num.acos

Num.acos : func(x: Num -> Num)

Computes the arc cosine of a number.

Argument Type Description Default
x Num The number for which the arc cosine is to be calculated. -

Return: The arc cosine of x in radians.

Example:

assert (0.0).acos().near(1.5707963267948966)

Num.acosh

Num.acosh : func(x: Num -> Num)

Computes the inverse hyperbolic cosine of a number.

Argument Type Description Default
x Num The number for which the inverse hyperbolic cosine is to be calculated. -

Return: The inverse hyperbolic cosine of x.

Example:

assert (1.0).acosh() == 0

Num.asin

Num.asin : func(x: Num -> Num)

Computes the arc sine of a number.

Argument Type Description Default
x Num The number for which the arc sine is to be calculated. -

Return: The arc sine of x in radians.

Example:

assert (0.5).asin().near(0.5235987755982989)

Num.asinh

Num.asinh : func(x: Num -> Num)

Computes the inverse hyperbolic sine of a number.

Argument Type Description Default
x Num The number for which the inverse hyperbolic sine is to be calculated. -

Return: The inverse hyperbolic sine of x.

Example:

assert (0.0).asinh() == 0

Num.atan

Num.atan : func(x: Num -> Num)

Computes the arc tangent of a number.

Argument Type Description Default
x Num The number for which the arc tangent is to be calculated. -

Return: The arc tangent of x in radians.

Example:

assert (1.0).atan().near(0.7853981633974483)

Num.atan2

Num.atan2 : func(x: Num, y: Num -> Num)

Computes the arc tangent of the quotient of two numbers.

Argument Type Description Default
x Num The numerator. -
y Num The denominator. -

Return: The arc tangent of x/y in radians.

Example:

assert Num.atan2(1, 1).near(0.7853981633974483)

Num.atanh

Num.atanh : func(x: Num -> Num)

Computes the inverse hyperbolic tangent of a number.

Argument Type Description Default
x Num The number for which the inverse hyperbolic tangent is to be calculated. -

Return: The inverse hyperbolic tangent of x.

Example:

assert (0.5).atanh().near(0.5493061443340549)

Num.cbrt

Num.cbrt : func(x: Num -> Num)

Computes the cube root of a number.

Argument Type Description Default
x Num The number for which the cube root is to be calculated. -

Return: The cube root of x.

Example:

assert (27.0).cbrt() == 3

Num.ceil

Num.ceil : func(x: Num -> Num)

Rounds a number up to the nearest integer.

Argument Type Description Default
x Num The number to be rounded up. -

Return: The smallest integer greater than or equal to x.

Example:

assert (3.2).ceil() == 4

Num.clamped

Num.clamped : func(x: Num, low: Num, high: Num -> Num)

Returns the given number clamped between two values so that it is within that range.

Argument Type Description Default
x Num The number to clamp. -
low Num The lowest value the result can take. -
high Num The highest value the result can take. -

Return: The first argument clamped between the other two arguments.

Example:

assert (2.5).clamped(5.5, 10.5) == 5.5

Num.copysign

Num.copysign : func(x: Num, y: Num -> Num)

Copies the sign of one number to another.

Argument Type Description Default
x Num The number whose magnitude will be copied. -
y Num The number whose sign will be copied. -

Return: A number with the magnitude of x and the sign of y.

Example:

assert (3.0).copysign(-1) == -3

Num.cos

Num.cos : func(x: Num -> Num)

Computes the cosine of a number (angle in radians).

Argument Type Description Default
x Num The angle in radians. -

Return: The cosine of x.

Example:

assert (0.0).cos() == 1

Num.cosh

Num.cosh : func(x: Num -> Num)

Computes the hyperbolic cosine of a number.

Argument Type Description Default
x Num The number for which the hyperbolic cosine is to be calculated. -

Return: The hyperbolic cosine of x.

Example:

assert (0.0).cosh() == 1

Num.erf

Num.erf : func(x: Num -> Num)

Computes the error function of a number.

Argument Type Description Default
x Num The number for which the error function is to be calculated. -

Return: The error function of x.

Example:

assert (0.0).erf() == 0

Num.erfc

Num.erfc : func(x: Num -> Num)

Computes the complementary error function of a number.

Argument Type Description Default
x Num The number for which the complementary error function is to be calculated. -

Return: The complementary error function of x.

Example:

assert (0.0).erfc() == 1

Num.exp

Num.exp : func(x: Num -> Num)

Computes the exponential function $e^x$ for a number.

Argument Type Description Default
x Num The exponent. -

Return: The value of $e^x$.

Example:

assert (1.0).exp().near(2.718281828459045)

Num.exp2

Num.exp2 : func(x: Num -> Num)

Computes $2^x$ for a number.

Argument Type Description Default
x Num The exponent. -

Return: The value of $2^x$.

Example:

assert (3.0).exp2() == 8

Num.expm1

Num.expm1 : func(x: Num -> Num)

Computes $e^x - 1$ for a number.

Argument Type Description Default
x Num The exponent. -

Return: The value of $e^x - 1$.

Example:

assert (1.0).expm1().near(1.7182818284590453)

Num.fdim

Num.fdim : func(x: Num, y: Num -> Num)

Computes the positive difference between two numbers.

Argument Type Description Default
x Num The first number. -
y Num The second number. -

Return: The positive difference $\max(0, x - y)$.

Example:

assert (5.0).fdim(3) == 2

Num.floor

Num.floor : func(x: Num -> Num)

Rounds a number down to the nearest integer.

Argument Type Description Default
x Num The number to be rounded down. -

Return: The largest integer less than or equal to x.

Example:

assert (3.7).floor() == 3

Num.hypot

Num.hypot : func(x: Num, y: Num -> Num)

Computes the Euclidean norm, $\sqrt{x^2 + y^2}$, of two numbers.

Argument Type Description Default
x Num The first number. -
y Num The second number. -

Return: The Euclidean norm of x and y.

Example:

assert Num.hypot(3, 4) == 5

Num.is_between

Num.is_between : func(x: Num, low: Num, high: Num -> Bool)

Determines if a number is between two numbers (inclusive).

Argument Type Description Default
x Num The integer to be checked. -
low Num One end of the range to check (inclusive). -
high Num The other end of the range to check (inclusive). -

Return: yes if a <= x and x <= b or b <= x and x <= a, otherwise no

Example:

assert (7.5).is_between(1, 10) == yes
assert (7.5).is_between(10, 1) == yes
assert (7.5).is_between(100, 200) == no
assert (7.5).is_between(1, 7.5) == yes

Num.isfinite

Num.isfinite : func(n: Num -> Bool)

Checks if a number is finite.

Argument Type Description Default
n Num The number to be checked. -

Return: yes if n is finite, no otherwise.

Example:

assert (1.0).isfinite() == yes
assert Num.INF.isfinite() == no

Num.isinf

Num.isinf : func(n: Num -> Bool)

Checks if a number is infinite.

Argument Type Description Default
n Num The number to be checked. -

Return: yes if n is infinite, no otherwise.

Example:

assert Num.INF.isinf() == yes
assert (1.0).isinf() == no

Num.j0

Num.j0 : func(x: Num -> Num)

Computes the Bessel function of the first kind of order 0.

Argument Type Description Default
x Num The number for which the Bessel function is to be calculated. -

Return: The Bessel function of the first kind of order 0 of x.

Example:

assert (0.0).j0() == 1

Num.j1

Num.j1 : func(x: Num -> Num)

Computes the Bessel function of the first kind of order 1.

Argument Type Description Default
x Num The number for which the Bessel function is to be calculated. -

Return: The Bessel function of the first kind of order 1 of x.

Example:

assert (0.0).j1() == 0

Num.log

Num.log : func(x: Num -> Num)

Computes the natural logarithm (base $e$) of a number.

Argument Type Description Default
x Num The number for which the natural logarithm is to be calculated. -

Return: The natural logarithm of x.

Example:

assert Num.E.log() == 1

Num.log10

Num.log10 : func(x: Num -> Num)

Computes the base-10 logarithm of a number.

Argument Type Description Default
x Num The number for which the base-10 logarithm is to be calculated. -

Return: The base-10 logarithm of x.

Example:

assert (100.0).log10() == 2

Num.log1p

Num.log1p : func(x: Num -> Num)

Computes $\log(1 + x)$ for a number.

Argument Type Description Default
x Num The number for which $\log(1 + x)$ is to be calculated. -

Return: The value of $\log(1 + x)$.

Example:

assert (1.0).log1p().near(0.6931471805599453)

Num.log2

Num.log2 : func(x: Num -> Num)

Computes the base-2 logarithm of a number.

Argument Type Description Default
x Num The number for which the base-2 logarithm is to be calculated. -

Return: The base-2 logarithm of x.

Example:

assert (8.0).log2() == 3

Num.logb

Num.logb : func(x: Num -> Num)

Computes the binary exponent (base-2 logarithm) of a number.

Argument Type Description Default
x Num The number for which the binary exponent is to be calculated. -

Return: The binary exponent of x.

Example:

assert (8.0).logb() == 3

Num.mix

Num.mix : func(amount: Num, x: Num, y: Num -> Num)

Interpolates between two numbers based on a given amount.

Argument Type Description Default
amount Num The interpolation factor (between 0 and 1). -
x Num The starting number. -
y Num The ending number. -

Return: The interpolated number between x and y based on amount.

Example:

assert (0.5).mix(10, 20) == 15
assert (0.25).mix(10, 20) == 12.5

Num.near

Num.near : func(x: Num, y: Num, ratio: Num = 1e-9, min_epsilon: Num = 1e-9 -> Bool)

Checks if two numbers are approximately equal within specified tolerances. If two numbers are within an absolute difference or the ratio between the two is small enough, they are considered near each other.

Argument Type Description Default
x Num The first number. -
y Num The second number. -
ratio Num The relative tolerance. Default is 1e-9. 1e-9
min_epsilon Num The absolute tolerance. Default is 1e-9. 1e-9

Return: yes if x and y are approximately equal within the specified tolerances, no otherwise.

Example:

assert (1.0).near(1.000000001) == yes
assert (100.0).near(110, ratio=0.1) == yes
assert (5.0).near(5.1, min_epsilon=0.1) == yes

Num.nextafter

Num.nextafter : func(x: Num, y: Num -> Num)

Computes the next representable value after a given number towards a specified direction.

Argument Type Description Default
x Num The starting number. -
y Num The direction towards which to find the next representable value. -

Return: The next representable value after x in the direction of y.

Example:

assert (1.0).nextafter(1.1) == 1.0000000000000002

Num.parse

Num.parse : func(text: Text, remainder: &Text? = none -> Num?)

Converts a text representation of a number into a floating-point number.

Argument Type Description Default
text Text The text containing the number. -
remainder &Text? If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. none

Return: The number represented by the text or none if the entire text can't be parsed as a number.

Example:

assert Num.parse("3.14") == 3.14
assert Num.parse("1e3") == 1000
assert Num.parse("1.5junk") == none
remainder : Text
assert Num.parse("1.5junk", &remainder) == 1.5
assert remainder == "junk"

Num.percent

Num.percent : func(n: Num, precision: Num = 0.01 -> Text)

Convert a number into a percentage text with a percent sign.

Argument Type Description Default
n Num The number to be converted to a percent. -
precision Num Round the percentage to this precision level. 0.01

Return: A text representation of the number as a percentage with a percent sign.

Example:

assert (0.5).percent() == "50%"
assert (1./3.).percent(2) == "34%"
assert (1./3.).percent(precision=0.0001) == "33.3333%"
assert (1./3.).percent(precision=10.) == "30%"

Num.rint

Num.rint : func(x: Num -> Num)

Rounds a number to the nearest integer, with ties rounded to the nearest even integer.

Argument Type Description Default
x Num The number to be rounded. -

Return: The nearest integer value of x.

Example:

assert (3.5).rint() == 4
assert (2.5).rint() == 2

Num.round

Num.round : func(x: Num -> Num)

Rounds a number to the nearest whole number integer.

Argument Type Description Default
x Num The number to be rounded. -

Return: The nearest integer value of x.

Example:

assert (2.3).round() == 2
assert (2.7).round() == 3

Num.significand

Num.significand : func(x: Num -> Num)

Extracts the significand (or mantissa) of a number.

Argument Type Description Default
x Num The number from which to extract the significand. -

Return: The significand of x.

Example:

assert (1234.567).significand() == 1.2056318359375

Num.sin

Num.sin : func(x: Num -> Num)

Computes the sine of a number (angle in radians).

Argument Type Description Default
x Num The angle in radians. -

Return: The sine of x.

Example:

assert (0.0).sin() == 0

Num.sinh

Num.sinh : func(x: Num -> Num)

Computes the hyperbolic sine of a number.

Argument Type Description Default
x Num The number for which the hyperbolic sine is to be calculated. -

Return: The hyperbolic sine of x.

Example:

assert (0.0).sinh() == 0

Num.sqrt

Num.sqrt : func(x: Num -> Num)

Computes the square root of a number.

Argument Type Description Default
x Num The number for which the square root is to be calculated. -

Return: The square root of x.

Example:

assert (16.0).sqrt() == 4

Num.tan

Num.tan : func(x: Num -> Num)

Computes the tangent of a number (angle in radians).

Argument Type Description Default
x Num The angle in radians. -

Return: The tangent of x.

Example:

assert (0.0).tan() == 0

Num.tanh

Num.tanh : func(x: Num -> Num)

Computes the hyperbolic tangent of a number.

Argument Type Description Default
x Num The number for which the hyperbolic tangent is to be calculated. -

Return: The hyperbolic tangent of x.

Example:

assert (0.0).tanh() == 0

Num.tgamma

Num.tgamma : func(x: Num -> Num)

Computes the gamma function of a number.

Argument Type Description Default
x Num The number for which the gamma function is to be calculated. -

Return: The gamma function of x.

Example:

assert (1.0).tgamma() == 1

Num.trunc

Num.trunc : func(x: Num -> Num)

Truncates a number to the nearest integer towards zero.

Argument Type Description Default
x Num The number to be truncated. -

Return: The integer part of x towards zero.

Example:

assert (3.7).trunc() == 3
assert (-3.7).trunc() == -3

Num.with_precision

Num.with_precision : func(n: Num, precision: Num -> Num)

Round a number to the given precision level (specified as 10, .1, .001 etc).

Argument Type Description Default
n Num The number to be rounded to a given precision. -
precision Num The precision to which the number should be rounded. -

Return: The number, rounded to the given precision level.

Example:

assert (0.1234567).with_precision(0.01) == 0.12
assert (123456.).with_precision(100) == 123500
assert (1234567.).with_precision(5) == 1234565

Num.y0

Num.y0 : func(x: Num -> Num)

Computes the Bessel function of the second kind of order 0.

Argument Type Description Default
x Num The number for which the Bessel function is to be calculated. -

Return: The Bessel function of the second kind of order 0 of x.

Example:

assert (1.0).y0().near(0.08825696421567698)

Num.y1

Num.y1 : func(x: Num -> Num)

Computes the Bessel function of the second kind of order 1.

Argument Type Description Default
x Num The number for which the Bessel function is to be calculated. -

Return: The Bessel function of the second kind of order 1 of x.

Example:

assert (1.0).y1().near(-0.7812128213002887)

Path

Path.accessed

Path.accessed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)

Gets the file access time of a file.

Argument Type Description Default
path Path The path of the file whose access time you want. -
follow_symlinks Bool Whether to follow symbolic links. yes

Return: A 64-bit unix epoch timestamp representing when the file or directory was last accessed, or none if no such file or directory exists.

Example:

assert (./file.txt).accessed() == Int64(1704221100)
assert (./not-a-file).accessed() == none

Path.append

Path.append : func(path: Path, text: Text, permissions: Int32 = Int32(0o644) -> Result)

Appends the given text to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.

Argument Type Description Default
path Path The path of the file to append to. -
text Text The text to append to the file. -
permissions Int32 The permissions to set on the file if it is being created. Int32(0o644)

Return: Either Success or Failure(reason).

Example:

(./log.txt).append("extra line\n")!

Path.append_bytes

Path.append_bytes : func(path: Path, bytes: [Byte], permissions: Int32 = Int32(0o644) -> Result)

Appends the given bytes to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.

Argument Type Description Default
path Path The path of the file to append to. -
bytes [Byte] The bytes to append to the file. -
permissions Int32 The permissions to set on the file if it is being created. Int32(0o644)

Return: Either Success or Failure(reason).

Example:

(./log.txt).append_bytes([104, 105])!

Path.base_name

Path.base_name : func(path: Path -> Text)

Returns the base name of the file or directory at the specified path.

Argument Type Description Default
path Path The path of the file or directory. -

Return: The base name of the file or directory.

Example:

assert (./path/to/file.txt).base_name() == "file.txt"

Path.by_line

Path.by_line : func(path: Path -> func(->Text?)?)

Returns an iterator that can be used to iterate over a file one line at a time, or returns none if the file could not be opened.

Argument Type Description Default
path Path The path of the file. -

Return: An iterator that can be used to get lines from a file one at a time or none if the file couldn't be read.

Example:

# Safely handle file not being readable:
if lines := (./file.txt).by_line()
    for line in lines
        say(line.upper())
else
    say("Couldn't read file!")

# Assume the file is readable and error if that's not the case:
for line in (/dev/stdin).by_line()!
    say(line.upper())

Path.byte_writer

Path.byte_writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(bytes:[Byte], close:Bool=no -> Result))

Returns a function that can be used to repeatedly write bytes to the same file.

The file writer will keep its file descriptor open after each write (unless the close argument is set to yes). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.

Argument Type Description Default
path Path The path of the file to write to. -
append Bool If set to yes, writes to the file will append. If set to no, then the first write to the file will overwrite its contents and subsequent calls will append. no
permissions Int32 The permissions to set on the file if it is created. Int32(0o644)

Return: Returns a function that can repeatedly write bytes to the same file. If close is set to yes, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.

Example:

write := (./file.txt).byte_writer()
write("Hello\n".utf8())!
write("world\n".utf8(), close=yes)!

Path.can_execute

Path.can_execute : func(path: Path -> Bool)

Returns whether or not a file can be executed by the current user/group.

Argument Type Description Default
path Path The path of the file to check. -

Return: yes if the file or directory exists and the current user has execute permissions, otherwise no.

Example:

assert (/bin/sh).can_execute() == yes
assert (/usr/include/stdlib.h).can_execute() == no
assert (/non/existant/file).can_execute() == no

Path.can_read

Path.can_read : func(path: Path -> Bool)

Returns whether or not a file can be read by the current user/group.

Argument Type Description Default
path Path The path of the file to check. -

Return: yes if the file or directory exists and the current user has read permissions, otherwise no.

Example:

assert (/usr/include/stdlib.h).can_read() == yes
assert (/etc/shadow).can_read() == no
assert (/non/existant/file).can_read() == no

Path.can_write

Path.can_write : func(path: Path -> Bool)

Returns whether or not a file can be written by the current user/group.

Argument Type Description Default
path Path The path of the file to check. -

Return: yes if the file or directory exists and the current user has write permissions, otherwise no.

Example:

assert (/tmp).can_write() == yes
assert (/etc/passwd).can_write() == no
assert (/non/existant/file).can_write() == no

Path.changed

Path.changed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)

Gets the file change time of a file.

This is the "ctime" of a file, which is not the file creation time.

Argument Type Description Default
path Path The path of the file whose change time you want. -
follow_symlinks Bool Whether to follow symbolic links. yes

Return: A 64-bit unix epoch timestamp representing when the file or directory was last changed, or none if no such file or directory exists.

Example:

assert (./file.txt).changed() == Int64(1704221100)
assert (./not-a-file).changed() == none

Path.child

Path.child : func(path: Path, child: Text -> Path)

Return a path that is a child of another path.

Argument Type Description Default
path Path The path of a directory. -
child Text The name of a child file or directory. -

Return: A new path representing the child.

Example:

assert (./directory).child("file.txt") == (./directory/file.txt)

Path.children

Path.children : func(path: Path, include_hidden = no -> [Path])

Returns a list of children (files and directories) within the directory at the specified path. Optionally includes hidden files. Child ordering is not specified.

Argument Type Description Default
path Path The path of the directory. -
include_hidden `` Whether to include hidden files (those starting with a .). no

Return: A list of paths for the children.

Example:

assert (./directory).children(include_hidden=yes) == [(./directory/.git), (./directory/foo.txt)]

Path.create_directory

Path.create_directory : func(path: Path, permissions = Int32(0o755), recursive = yes -> Result)

Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.

Argument Type Description Default
path Path The path of the directory to create. -
permissions `` The permissions to set on the new directory. Int32(0o755)
recursive `` If set to yes, then recursively create any parent directories if they don't exist, otherwise fail if the parent directory does not exist. When set to yes, this function behaves like mkdir -p. yes

Return: Either Success or Failure(reason).

Example:

(./new_directory).create_directory()!

Path.current_dir

Path.current_dir : func(-> Path)

Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.

Return: The absolute path of the current directory.

Example:

assert Path.current_dir() == (/home/user/tomo)

Path.each_child

Path.each_child : func(path: Path, include_hidden = no -> func(->Path?)?)

Returns an iterator over the children (files and directories) within the directory at the specified path. Optionally includes hidden files. Iteration order is not specified.

Argument Type Description Default
path Path The path of the directory. -
include_hidden `` Whether to include hidden files (those starting with a .). no

Return: An iterator over the children in a directory or none if the path is not a directory or a symlink to a directory.

Example:

for child in (/dir).each_child()
    say("Child: $child")

Path.exists

Path.exists : func(path: Path -> Bool)

Checks if a file or directory exists at the specified path.

Argument Type Description Default
path Path The path to check. -

Return: True if the file or directory exists, False otherwise.

Example:

assert (/).exists() == yes

Path.expand_home

Path.expand_home : func(path: Path -> Path)

For home-based paths (those starting with ~), expand the path to replace the tilde with and absolute path to the user's $HOME directory.

Argument Type Description Default
path Path The path to expand. -

Return: If the path does not start with a ~, then return it unmodified. Otherwise, replace the ~ with an absolute path to the user's home directory.

Example:

# Assume current user is 'user'
assert (~/foo).expand_home() == (/home/user/foo)
# No change
assert (/foo).expand_home() == (/foo)

Path.extension

Path.extension : func(path: Path, full: Bool = yes -> Text)

Returns the file extension of the file at the specified path. Optionally returns the full extension.

Argument Type Description Default
path Path The path of the file. -
full Bool Whether to return everything after the first . in the base name, or only the last part of the extension. yes

Return: The file extension (not including the leading .) or an empty text if there is no file extension.

Example:

assert (./file.tar.gz).extension() == "tar.gz"
assert (./file.tar.gz).extension(full=no) == "gz"
assert (/foo).extension() == ""
assert (./.git).extension() == ""

Path.files

Path.files : func(path: Path, include_hidden: Bool = no -> [Path])

Returns a list of files within the directory at the specified path. Optionally includes hidden files.

Argument Type Description Default
path Path The path of the directory. -
include_hidden Bool Whether to include hidden files (those starting with a .). no

Return: A list of file paths.

Example:

assert (./directory).files(include_hidden=yes) == [(./directory/file1.txt), (./directory/file2.txt)]

Path.glob

Path.glob : func(path: Path -> [Path])

Perform a globbing operation and return a list of matching paths. Some glob specific details:

  • The paths "." and ".." are not included in any globbing results.

  • Files or directories that begin with "." will not match *, but will match .*.

  • Globs do support {a,b} syntax for matching files that match any of several choices of patterns.

  • The shell-style syntax ** for matching subdirectories is not supported.

Argument Type Description Default
path Path The path of the directory which may contain special globbing characters like *, ?, or {...} -

Return: A list of file paths that match the glob.

Example:

# Current directory includes: foo.txt, baz.txt, qux.jpg, .hidden
assert (./*).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]
assert (./*.txt).glob() == [(./foo.txt), (./baz.txt)]
assert (./*.{txt,jpg}).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]
assert (./.*).glob() == [(./.hidden)]

# Globs with no matches return an empty list:
assert (./*.xxx).glob() == []

Path.group

Path.group : func(path: Path, follow_symlinks: Bool = yes -> Text?)

Get the owning group of a file or directory.

Argument Type Description Default
path Path The path whose owning group to get. -
follow_symlinks Bool Whether to follow symbolic links. yes

Return: The name of the group which owns the file or directory, or none if the path does not exist.

Example:

assert (/bin).group() == "root"
assert (/non/existent/file).group() == none

Path.has_extension

Path.has_extension : func(path: Path, extension: Text -> Bool)

Return whether or not a path has a given file extension.

Argument Type Description Default
path Path A path. -
extension Text A file extension (leading . is optional). If empty, the check will test if the file does not have any file extension. -

Return: Whether or not the path has the given extension.

Example:

assert (/foo.txt).has_extension("txt") == yes
assert (/foo.txt).has_extension(".txt") == yes
assert (/foo.tar.gz).has_extension("gz") == yes
assert (/foo.tar.gz).has_extension("zip") == no

Path.is_directory

Path.is_directory : func(path: Path, follow_symlinks = yes -> Bool)

Checks if the path represents a directory. Optionally follows symbolic links.

Argument Type Description Default
path Path The path to check. -
follow_symlinks `` Whether to follow symbolic links. yes

Return: True if the path is a directory, False otherwise.

Example:

assert (./directory/).is_directory() == yes
assert (./file.txt).is_directory() == no

Path.is_file

Path.is_file : func(path: Path, follow_symlinks = yes -> Bool)

Checks if the path represents a file. Optionally follows symbolic links.

Argument Type Description Default
path Path The path to check. -
follow_symlinks `` Whether to follow symbolic links. yes

Return: True if the path is a file, False otherwise.

Example:

assert (./file.txt).is_file() == yes
assert (./directory/).is_file() == no

Path.is_socket

Path.is_socket : func(path: Path, follow_symlinks = yes -> Bool)

Checks if the path represents a socket. Optionally follows symbolic links.

Argument Type Description Default
path Path The path to check. -
follow_symlinks `` Whether to follow symbolic links. yes

Return: True if the path is a socket, False otherwise.

Example:

assert (./socket).is_socket() == yes

Path.is_symlink

Path.is_symlink : func(path: Path -> Bool)

Checks if the path represents a symbolic link.

Argument Type Description Default
path Path The path to check. -

Return: True if the path is a symbolic link, False otherwise.

Example:

assert (./link).is_symlink() == yes

Path.lines

Path.lines : func(path: Path -> [Text]?)

Returns a list with the lines of text in a file or returns none if the file could not be opened.

Argument Type Description Default
path Path The path of the file. -

Return: A list of the lines in a file or none if the file couldn't be read.

Example:

lines := (./file.txt).lines()!

Path.matches_glob

Path.matches_glob : func(path: Path, glob: Text -> Bool)

Return whether or not a path matches a given glob.

Argument Type Description Default
path Path The path to check. -
glob Text The glob pattern to check. -

Return: Whether or not the path matches the given glob.

Example:

assert (./file.txt).matches_glob("*.txt")
assert (./file.c).matches_glob("*.{c,h}")

Path.modified

Path.modified : func(path: Path, follow_symlinks: Bool = yes -> Int64?)

Gets the file modification time of a file.

Argument Type Description Default
path Path The path of the file whose modification time you want. -
follow_symlinks Bool Whether to follow symbolic links. yes

Return: A 64-bit unix epoch timestamp representing when the file or directory was last modified, or none if no such file or directory exists.

Example:

assert (./file.txt).modified() == Int64(1704221100)
assert (./not-a-file).modified() == none

Path.move

Path.move : func(path: Path, dest: Path, allow_overwriting = no -> Result)

Moves the file or directory from one location to another.

Argument Type Description Default
path Path The path to move. -
dest Path The destination to move the path to. -
allow_overwriting `` Whether to permit overwriting the destination if it is an existing file or directory. no

Return: Either Success or Failure(reason).

Example:

(./file.txt).move(/tmp/renamed.txt)!

Path.owner

Path.owner : func(path: Path, follow_symlinks: Bool = yes -> Text?)

Get the owning user of a file or directory.

Argument Type Description Default
path Path The path whose owner to get. -
follow_symlinks Bool Whether to follow symbolic links. yes

Return: The name of the user who owns the file or directory, or none if the path does not exist.

Example:

assert (/bin).owner() == "root"
assert (/non/existent/file).owner() == none

Path.parent

Path.parent : func(path: Path -> Path?)

Returns the parent directory of the file or directory at the specified path.

Argument Type Description Default
path Path The path of the file or directory. -

Return: The path of the parent directory or none if the path is (/) (the file root).

Example:

assert (./path/to/file.txt).parent() == (./path/to/)

Path.read

Path.read : func(path: Path -> Text?)

Reads the contents of the file at the specified path or none if the file could not be read.

Argument Type Description Default
path Path The path of the file to read. -

Return: The contents of the file. If the file could not be read, none will be returned. If the file can be read, but is not valid UTF8 data, an error will be raised.

Example:

assert (./hello.txt).read() == "Hello"
assert (./nosuchfile.xxx).read() == none

Path.read_bytes

Path.read_bytes : func(path: Path, limit: Int? = none -> [Byte]?)

Reads the contents of the file at the specified path or none if the file could not be read.

Argument Type Description Default
path Path The path of the file to read. -
limit Int? A limit to how many bytes should be read. none

Return: The byte contents of the file. If the file cannot be read, none will be returned.

Example:

assert (./hello.txt).read_bytes()! == [72, 101, 108, 108, 111]
assert (./nosuchfile.xxx).read_bytes() == none

Path.relative_to

Path.relative_to : func(path: Path, relative_to = (./) -> Path)

Returns the path relative to a given base path. By default, the base path is the current directory.

Argument Type Description Default
path Path The path to convert. -
relative_to `` The base path for the relative path. (./)

Return: A relative path from the reference point to the given path.

Example:

assert (./path/to/file.txt).relative_to((./path)) == (./to/file.txt)
assert (/tmp/foo).relative_to((/tmp)) == (./foo)

Path.remove

Path.remove : func(path: Path, ignore_missing = no -> Result)

Removes the file or directory at the specified path. A runtime error is raised if something goes wrong.

Argument Type Description Default
path Path The path to remove. -
ignore_missing `` Whether to ignore errors if the file or directory does not exist. no

Return: Either Success or Failure(reason).

Example:

(./file.txt).remove()!

Path.resolved

Path.resolved : func(path: Path, relative_to = (./) -> Path)

Resolves the absolute path of the given path relative to a base path. By default, the base path is the current directory.

Argument Type Description Default
path Path The path to resolve. -
relative_to `` The base path for resolution. (./)

Return: The resolved absolute path.

Example:

assert (~/foo).resolved() == (/home/user/foo)
assert (./path/to/file.txt).resolved(relative_to=(/foo)) == (/foo/path/to/file.txt)

Path.set_owner

Path.set_owner : func(path: Path, owner: Text? = none, group: Text? = none, follow_symlinks: Bool = yes -> Result)

Set the owning user and/or group for a path.

Argument Type Description Default
path Path The path to change the permissions for. -
owner Text? If non-none, the new user to assign to be the owner of the file. none
group Text? If non-none, the new group to assign to be the owner of the file. none
follow_symlinks Bool Whether to follow symbolic links. yes

Return: Either Success or Failure(reason).

Example:

(./file.txt).set_owner(owner="root", group="wheel")!

Path.sibling

Path.sibling : func(path: Path, name: Text -> Path)

Return a path that is a sibling of another path (i.e. has the same parent, but a different name). This is equivalent to .parent().child(name)

Argument Type Description Default
path Path A path. -
name Text The name of a sibling file or directory. -

Return: A new path representing the sibling.

Example:

assert (/foo/baz).sibling("doop") == (/foo/doop)

Path.subdirectories

Path.subdirectories : func(path: Path, include_hidden = no -> [Path])

Returns a list of subdirectories within the directory at the specified path. Optionally includes hidden subdirectories.

Argument Type Description Default
path Path The path of the directory. -
include_hidden `` Whether to include hidden subdirectories (those starting with a .) no

Return: A list of subdirectory paths.

Example:

assert (./directory).subdirectories() == [(./directory/subdir1), (./directory/subdir2)]
assert (./directory).subdirectories(include_hidden=yes) == [(./directory/.git), (./directory/subdir1), (./directory/subdir2)]

Path.unique_directory

Path.unique_directory : func(path: Path -> Path)

Generates a unique directory path based on the given path. Useful for creating temporary directories.

Argument Type Description Default
path Path The base path for generating the unique directory. The last six letters of this path must be XXXXXX. -

Return: A unique directory path after creating the directory.

Example:

created := (/tmp/my-dir.XXXXXX).unique_directory()
assert created.is_directory() == yes
created.remove()!

Path.walk

Path.walk : func(path: Path, include_hidden = no, follow_symlinks: Bool = no -> func(->Path?))

Returns an iterator that efficiently recursively walks over every file and subdirectory in a given directory. The iteration order is not defined, but in practice it may look a lot like a breadth-first traversal.

The path itself is always included in the iteration.

Argument Type Description Default
path Path The path to begin the walk. -
include_hidden `` Whether to include hidden files (those starting with a .) no
follow_symlinks Bool Whether to follow symbolic links. Caution: if set to 'yes', it is possible for this iterator to get stuck in a loop, using increasingly large amounts of memory. no

Return: An iterator that recursively walks over every file and subdirectory.

Example:

for p in (/tmp).walk()
    say("File or dir: $p")

# The path itself is always included:
assert [p for p in (./file.txt).walk()] == [(./file.txt)]

Path.write

Path.write : func(path: Path, text: Text, permissions = Int32(0o644) -> Result)

Writes the given text to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.

Argument Type Description Default
path Path The path of the file to write to. -
text Text The text to write to the file. -
permissions `` The permissions to set on the file if it is created. Int32(0o644)

Return: Either Success or Failure(reason).

Example:

(./file.txt).write("Hello, world!")!

Path.write_bytes

Path.write_bytes : func(path: Path, bytes: [Byte], permissions = Int32(0o644) -> Result)

Writes the given bytes to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.

Argument Type Description Default
path Path The path of the file to write to. -
bytes [Byte] A list of bytes to write to the file. -
permissions `` The permissions to set on the file if it is created. Int32(0o644)

Return: Either Success or Failure(reason).

Example:

(./file.txt).write_bytes([104, 105])!

Path.write_unique

Path.write_unique : func(path: Path, text: Text -> Path)

Writes the given text to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.

Argument Type Description Default
path Path The base path for generating the unique file. This path must include the string XXXXXX in the file base name. -
text Text The text to write to the file. -

Return: The path of the newly created unique file.

Example:

created := (./file-XXXXXX.txt).write_unique("Hello, world!")!
assert created == (./file-27QHtq.txt)
assert created.read()! == "Hello, world!"
created.remove()!

Path.write_unique_bytes

Path.write_unique_bytes : func(path: Path, bytes: [Byte] -> Path)

Writes the given bytes to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.

Argument Type Description Default
path Path The base path for generating the unique file. This path must include the string XXXXXX in the file base name. -
bytes [Byte] The bytes to write to the file. -

Return: The path of the newly created unique file.

Example:

created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!
assert created == (./file-27QHtq.txt)
assert created.read_bytes()! == [1, 2, 3]
created.remove()!

Path.writer

Path.writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(text:Text, close:Bool=no -> Result))

Returns a function that can be used to repeatedly write to the same file.

The file writer will keep its file descriptor open after each write (unless the close argument is set to yes). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.

Argument Type Description Default
path Path The path of the file to write to. -
append Bool If set to yes, writes to the file will append. If set to no, then the first write to the file will overwrite its contents and subsequent calls will append. no
permissions Int32 The permissions to set on the file if it is created. Int32(0o644)

Return: Returns a function that can repeatedly write to the same file. If close is set to yes, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.

Example:

write := (./file.txt).writer()
write("Hello\n")!
write("world\n", close=yes)!

Table

Table.clear

Table.clear : func(t: &{K:V} -> Void)

Removes all key-value pairs from the table.

Argument Type Description Default
t &{K:V} The reference to the table. -

Return: Nothing.

Example:

t := &{"A":1}
t.clear()
assert t[] == {}

Table.difference

Table.difference : func(t: {K:V}, other: {K:V} -> {K:V})

Return a table whose key/value pairs correspond to keys only present in one table, but not the other.

Argument Type Description Default
t {K:V} The base table. -
other {K:V} The other table. -

Return: A table containing the common key/value pairs whose keys only appear in one table.

Example:

t1 := {"A": 1, "B": 2, "C": 3}
t2 := {"B": 2, "C":30, "D": 40}
assert t1.difference(t2) == {"A": 1, "D": 40}

Table.get

Table.get : func(t: {K:V}, key: K -> V?)

Retrieves the value associated with a key, or returns none if the key is not present.

Default values for the table are ignored.

Argument Type Description Default
t {K:V} The table. -
key K The key whose associated value is to be retrieved. -

Return: The value associated with the key or none if the key is not found.

Example:

t := {"A": 1, "B": 2}
assert t.get("A") == 1
assert t.get("????") == none
assert t.get("A")! == 1
assert t.get("????") or 0 == 0

Table.get_or_set

Table.get_or_set : func(t: &{K:V}, key: K, default: V -> V?)

If the given key is in the table, return the associated value. Otherwise, insert the given default value into the table and return it.

If no default value is provided explicitly, but the table has a default value associated with it, the table's default value will be used. The default value is only evaluated if the key is missing.

Argument Type Description Default
t &{K:V} The table. -
key K The key whose associated value is to be retrieved. -
default V The default value to insert and return if the key is not present in the table. -

Return: Either the value associated with the key (if present) or the default value. The table will be mutated if the key is not already present.

Example:

t := &{"A": @[1, 2, 3]; default=@[]}
t.get_or_set("A").insert(4)
t.get_or_set("B").insert(99)
assert t["A"][] == [1, 2, 3, 4]
assert t["B"][] == [99]
assert t.get_or_set("C", @[0, 0, 0])[] == [0, 0, 0]

Table.has

Table.has : func(t: {K:V}, key: K -> Bool)

Checks if the table contains a specified key.

Argument Type Description Default
t {K:V} The table. -
key K The key to check for presence. -

Return: yes if the key is present, no otherwise.

Example:

assert {"A": 1, "B": 2}.has("A") == yes
assert {"A": 1, "B": 2}.has("xxx") == no

Table.intersection

Table.intersection : func(t: {K:V}, other: {K:V} -> {K:V})

Return a table with only the matching key/value pairs that are common to both tables.

Argument Type Description Default
t {K:V} The base table. -
other {K:V} The other table. -

Return: A table containing the common key/value pairs shared between two tables.

Example:

t1 := {"A": 1, "B": 2, "C": 3}
t2 := {"B": 2, "C":30, "D": 40}
assert t1.intersection(t2) == {"B": 2}

Table.remove

Table.remove : func(t: {K:V}, key: K -> Void)

Removes the key-value pair associated with a specified key.

Argument Type Description Default
t {K:V} The reference to the table. -
key K The key of the key-value pair to remove. -

Return: Nothing.

Example:

t := &{"A": 1, "B": 2}
t.remove("A")
assert t == {"B": 2}

Table.set

Table.set : func(t: {K:V}, key: K, value: V -> Void)

Sets or updates the value associated with a specified key.

Argument Type Description Default
t {K:V} The reference to the table. -
key K The key to set or update. -
value V The value to associate with the key. -

Return: Nothing.

Example:

t := &{"A": 1, "B": 2}
t.set("C", 3)
assert t == {"A": 1, "B": 2, "C": 3}

Table.with

Table.with : func(t: {K:V}, other: {K:V} -> {K:V})

Return a copy of a table with values added from another table

Argument Type Description Default
t {K:V} The base table. -
other {K:V} The other table from which new key/value pairs will be added. -

Return: The original table, but with values from the other table added.

Example:

t := {"A": 1, "B": 2}
assert t.with({"B": 20, "C": 30}) == {"A": 1, "B": 20, "C": 30}

Table.with_fallback

Table.with_fallback : func(t: {K:V}, fallback: {K:V}? -> {K:V})

Return a copy of a table with a different fallback table.

Argument Type Description Default
t {K:V} The table whose fallback will be replaced. -
fallback {K:V}? The new fallback table value. -

Return: The original table with a different fallback.

Example:

t := {"A": 1; fallback={"B": 2}}
t2 := t.with_fallback({"B": 3})
assert t2["B"] == 3
t3 := t.with_fallback(none)
assert t3["B"] == none

Table.without

Table.without : func(t: {K:V}, other: {K:V} -> {K:V})

Return a copy of a table, but without any of the exact key/value pairs found in the other table.

Only exact key/value pairs will be discarded. Keys with a non-matching value will be kept.

Argument Type Description Default
t {K:V} The base table. -
other {K:V} The other table whose key/value pairs will be omitted. -

Return: The original table, but without the key/value pairs from the other table.

Example:

t := {"A": 1, "B": 2, "C": 3}
assert t.without({"B": 2, "C": 30, "D": 40}) == {"A": 1, "C": 3}

Text

Text.as_c_string

Text.as_c_string : func(text: Text -> CString)

Converts a Text value to a C-style string.

Argument Type Description Default
text Text The text to be converted to a C-style string. -

Return: A C-style string (CString) representing the text.

Example:

assert "Hello".as_c_string() == CString("Hello")

Text.at

Text.at : func(text: Text, index: Int -> Text)

Get the graphical cluster at a given index. This is similar to str[i] with ASCII text, but has more correct behavior for unicode text.

Negative indices are counted from the back of the text, so -1 means the last cluster, -2 means the second-to-last, and so on.

Argument Type Description Default
text Text The text from which to get a cluster. -
index Int The index of the graphical cluster (1-indexed). -

Return: A Text with the single graphical cluster at the given index.

Example:

assert "Amélie".at(3) == "é"

Text.by_line

Text.by_line : func(text: Text -> func(->Text?))

Returns an iterator function that can be used to iterate over the lines in a text.

This function ignores a trailing newline if there is one. If you don't want this behavior, use text.by_split($/{1 nl}/) instead.

Argument Type Description Default
text Text The text to be iterated over, line by line. -

Return: An iterator function that returns one line at a time, until it runs out and returns none.

Example:

text := "
    line one
    line two
"
lines := [line for line in text.by_line()]
assert lines == ["line one", "line two"]

Text.by_split

Text.by_split : func(text: Text, delimiter: Text = "" -> func(->Text?))

Returns an iterator function that can be used to iterate over text separated by a delimiter.

To split based on a set of delimiters, use Text.by_split_any(). If an empty text is given as the delimiter, then each split will be the graphical clusters of the text.

Argument Type Description Default
text Text The text to be iterated over in delimited chunks. -
delimiter Text An exact delimiter to use for splitting the text. ""

Return: An iterator function that returns one chunk of text at a time, separated by the given delimiter, until it runs out and returns none.

Example:

text := "one,two,three"
chunks := [chunk for chunk in text.by_split(",")]
assert chunks == ["one", "two", "three"]

Text.by_split_any

Text.by_split_any : func(text: Text, delimiters: Text = " $\t\r\n" -> func(->Text?))

Returns an iterator function that can be used to iterate over text separated by one or more characters (grapheme clusters) from a given text of delimiters.

Splitting will occur on every place where one or more of the grapheme clusters in delimiters occurs. To split based on an exact delimiter, use Text.by_split().

Argument Type Description Default
text Text The text to be iterated over in delimited chunks. -
delimiters Text Grapheme clusters to use for splitting the text. " $\t\r\n"

Return: An iterator function that returns one chunk of text at a time, separated by the given delimiter characters, until it runs out and returns none.

Example:

text := "one,two,;,three"
chunks := [chunk for chunk in text.by_split_any(",;")]
assert chunks == ["one", "two", "three"]

Text.caseless_equals

Text.caseless_equals : func(a: Text, b: Text, language: Text = "C" -> Bool)

Checks whether two texts are equal, ignoring the casing of the letters (i.e. case-insensitive comparison).

Argument Type Description Default
a Text The first text to compare case-insensitively. -
b Text The second text to compare case-insensitively. -
language Text The ISO 639 language code for which casing rules to use. "C"

Return: yes if a and b are equal to each other, ignoring casing, otherwise no.

Example:

assert "A".caseless_equals("a") == yes

# Turkish lowercase "I" is "ı" (dotless I), not "i"
assert "I".caseless_equals("i", language="tr_TR") == no

Text.codepoint_names

Text.codepoint_names : func(text: Text -> [Text])

Returns a list of the names of each codepoint in the text.

Argument Type Description Default
text Text The text from which to extract codepoint names. -

Return: A list of codepoint names ([Text]).

Example:

assert "Amélie".codepoint_names() == [
    "LATIN CAPITAL LETTER A",
    "LATIN SMALL LETTER M",
    "LATIN SMALL LETTER E WITH ACUTE",
    "LATIN SMALL LETTER L",
    "LATIN SMALL LETTER I",
    "LATIN SMALL LETTER E",
]

Text.distance

Text.distance : func(a: Text, b: Text, language: Text = "C" -> Num)

Get an approximate distance between two texts, such that when the distance is small, the texts are similar and when the distance is large, the texts are dissimilar.

The exact distance algorithm is not specified and may be subject to change over time.

Argument Type Description Default
a Text The first text to compare. -
b Text The second text to compare. -
language Text The ISO 639 language code for which character width to use. "C"

Return: The distance between the two texts (larger means more dissimilar).

Example:

assert "hello".distance("hello") == 0
texts := &["goodbye", "hello", "hallo"]
texts.sort(func(a,b:&Text) a.distance("hello") <> b.distance("hello"))
assert texts == ["hello", "hallo", "goodbye"]

Text.ends_with

Text.ends_with : func(text: Text, suffix: Text, remainder: &Text? = none -> Bool)

Checks if the Text ends with a literal suffix text.

Argument Type Description Default
text Text The text to be searched. -
suffix Text The literal suffix text to check for. -
remainder &Text? If non-none, this value will be set to the rest of the text up to the trailing suffix. If the suffix is not found, this value will be set to the original text. none

Return: yes if the text has the target, no otherwise.

Example:

assert "hello world".ends_with("world") == yes
remainder : Text
assert "hello world".ends_with("world", &remainder) == yes
assert remainder == "hello "

Text.find

Text.find : func(text: Text, target: Text, start: Int = 1 -> Int)

Find a substring within a text and return its index, if found.

Argument Type Description Default
text Text The text to be searched. -
target Text The target text to find. -
start Int The index at which to begin searching. 1

Return: The index where the first occurrence of target appears, or none if it is not found.

Example:

assert "one two".find("one") == 1
assert "one two".find("two") == 5
assert "one two".find("three") == none
assert "one two".find("o", start=2) == 7

Text.from

Text.from : func(text: Text, first: Int -> Text)

Get a slice of the text, starting at the given position.

A negative index counts backwards from the end of the text, so -1 refers to the last cluster, -2 the second-to-last, etc. Slice ranges will be truncated to the length of the text.

Argument Type Description Default
text Text The text to be sliced. -
first Int The index to begin the slice. -

Return: The text from the given grapheme cluster to the end of the text.

Example:

assert "hello".from(2) == "ello"
assert "hello".from(-2) == "lo"

Text.from_c_string

Text.from_c_string : func(str: CString -> Text)

Converts a C-style string to a Text value.

Argument Type Description Default
str CString The C-style string to be converted. -

Return: A Text value representing the C-style string.

Example:

assert Text.from_c_string(CString("Hello")) == "Hello"

Text.from_codepoint_names

Text.from_codepoint_names : func(codepoint_names: [Text] -> [Text])

Returns text that has the given codepoint names (according to the Unicode specification) as its codepoints.

The text will be normalized, so the resulting text's codepoints may not exactly match the input codepoints.

Argument Type Description Default
codepoint_names [Text] The names of each codepoint in the desired text (case-insentive). -

Return: A new text with the specified codepoints after normalization has been applied. Any invalid names are ignored.

Example:

text := Text.from_codepoint_names([
    "LATIN CAPITAL LETTER A WITH RING ABOVE",
    "LATIN SMALL LETTER K",
    "LATIN SMALL LETTER E",
])
assert text == "Åke"

Text.from_utf16

Text.from_utf16 : func(bytes: [Int16] -> [Text])

Returns text that has been constructed from the given UTF16 sequence.

The text will be normalized, so the resulting text's UTF16 sequence may not exactly match the input.

Argument Type Description Default
bytes [Int16] The UTF-16 integers of the desired text. -

Return: A new text based on the input UTF16 sequence after normalization has been applied.

Example:

assert Text.from_utf16([197, 107, 101]) == "Åke"
assert Text.from_utf16([12371, 12435, 12395, 12385, 12399, 19990, 30028]) == "こんにちは世界"

Text.from_utf32

Text.from_utf32 : func(codepoints: [Int32] -> [Text])

Returns text that has been constructed from the given UTF32 codepoints.

The text will be normalized, so the resulting text's codepoints may not exactly match the input codepoints.

Argument Type Description Default
codepoints [Int32] The UTF32 codepoints in the desired text. -

Return: A new text with the specified codepoints after normalization has been applied.

Example:

assert Text.from_utf32([197, 107, 101]) == "Åke"

Text.from_utf8

Text.from_utf8 : func(bytes: [Byte] -> [Text])

Returns text that has been constructed from the given UTF8 bytes.

The text will be normalized, so the resulting text's UTF8 bytes may not exactly match the input.

Argument Type Description Default
bytes [Byte] The UTF-8 bytes of the desired text. -

Return: A new text based on the input UTF8 bytes after normalization has been applied.

Example:

assert Text.from_utf8([195, 133, 107, 101]) == "Åke"

Text.has

Text.has : func(text: Text, target: Text -> Bool)

Checks if the Text contains some target text.

Argument Type Description Default
text Text The text to be searched. -
target Text The text to search for. -

Return: yes if the target text is found, no otherwise.

Example:

assert "hello world".has("wo") == yes
assert "hello world".has("xxx") == no

Text.join

Text.join : func(glue: Text, pieces: [Text] -> Text)

Joins a list of text pieces with a specified glue.

Argument Type Description Default
glue Text The text used to join the pieces. -
pieces [Text] The list of text pieces to be joined. -

Return: A single Text value with the pieces joined by the glue.

Example:

assert ", ".join(["one", "two", "three"]) == "one, two, three"

Text.left_pad

Text.left_pad : func(text: Text, width: Int, pad: Text = " ", language: Text = "C" -> Text)

Pad some text on the left side so it reaches a target width.

Argument Type Description Default
text Text The text to pad. -
width Int The target width. -
pad Text The padding text. " "
language Text The ISO 639 language code for which character width to use. "C"

Return: Text with length at least width, with extra padding on the left as needed. If pad has length greater than 1, it may be partially repeated to reach the exact desired length.

Example:

assert "x".left_pad(5) == "    x"
assert "x".left_pad(5, "ABC") == "ABCAx"

Text.lines

Text.lines : func(text: Text -> [Text])

Splits the text into a list of lines of text, preserving blank lines, ignoring trailing newlines, and handling \r\n the same as \n.

Argument Type Description Default
text Text The text to be split into lines. -

Return: A list of substrings resulting from the split.

Example:

assert "one\ntwo\nthree".lines() == ["one", "two", "three"]
assert "one\ntwo\nthree\n".lines() == ["one", "two", "three"]
assert "one\ntwo\nthree\n\n".lines() == ["one", "two", "three", ""]
assert "one\r\ntwo\r\nthree\r\n".lines() == ["one", "two", "three"]
assert "".lines() == []

Text.lower

Text.lower : func(text: Text, language: Text = "C" -> Text)

Converts all characters in the text to lowercase.

Argument Type Description Default
text Text The text to be converted to lowercase. -
language Text The ISO 639 language code for which casing rules to use. "C"

Return: The lowercase version of the text.

Example:

assert "AMÉLIE".lower() == "amélie"
assert "I".lower(language="tr_TR") == "ı"

Text.matches_glob

Text.matches_glob : func(path: Text, glob: Text -> Bool)

Return whether or not the text matches the given glob.

Argument Type Description Default
path Text The text to check. -
glob Text The glob pattern to check. -

Return: Whether or not the text matches the given glob.

Example:

assert "hello world".matches_glob("h* *d")

Text.middle_pad

Text.middle_pad : func(text: Text, width: Int, pad: Text = " ", language: Text = "C" -> Text)

Pad some text on the left and right side so it reaches a target width.

Argument Type Description Default
text Text The text to pad. -
width Int The target width. -
pad Text The padding text. " "
language Text The ISO 639 language code for which character width to use. "C"

Return: Text with length at least width, with extra padding on the left and right as needed. If pad has length greater than 1, it may be partially repeated to reach the exact desired length.

Example:

assert "x".middle_pad(6) == "  x   "
assert "x".middle_pad(10, "ABC") == "ABCAxABCAB"

Text.quoted

Text.quoted : func(text: Text, color: Bool = no, quotation_mark: Text = `"` -> Text)

Formats the text with quotation marks and escapes.

Argument Type Description Default
text Text The text to be quoted. -
color Bool Whether to add color formatting. no
quotation_mark Text The quotation mark to use. "

Return: The text formatted as a quoted text.

Example:

assert "one\ntwo".quoted() == "\"one\\ntwo\""

Text.repeat

Text.repeat : func(text: Text, count: Int -> Text)

Repeat some text multiple times.

Argument Type Description Default
text Text The text to repeat. -
count Int The number of times to repeat it. (Negative numbers are equivalent to zero). -

Return: The text repeated the given number of times.

Example:

assert "Abc".repeat(3) == "AbcAbcAbc"

Text.replace

Text.replace : func(text: Text, target: Text, replacement: Text -> Text)

Replaces occurrences of a target text with a replacement text.

Argument Type Description Default
text Text The text in which to perform replacements. -
target Text The target text to be replaced. -
replacement Text The text to replace the target with. -

Return: The text with occurrences of the target replaced.

Example:

assert "Hello world".replace("world", "there") == "Hello there"

Text.reversed

Text.reversed : func(text: Text -> Text)

Return a text that has the grapheme clusters in reverse order.

Argument Type Description Default
text Text The text to reverse. -

Return: A reversed version of the text.

Example:

assert "Abc".reversed() == "cbA"

Text.right_pad

Text.right_pad : func(text: Text, width: Int, pad: Text = " ", language: Text = "C" -> Text)

Pad some text on the right side so it reaches a target width.

Argument Type Description Default
text Text The text to pad. -
width Int The target width. -
pad Text The padding text. " "
language Text The ISO 639 language code for which character width to use. "C"

Return: Text with length at least width, with extra padding on the right as needed. If pad has length greater than 1, it may be partially repeated to reach the exact desired length.

Example:

assert "x".right_pad(5) == "x    "
assert "x".right_pad(5, "ABC") == "xABCA"

Text.slice

Text.slice : func(text: Text, from: Int = 1, to: Int = -1 -> Text)

Get a slice of the text.

A negative index counts backwards from the end of the text, so -1 refers to the last cluster, -2 the second-to-last, etc. Slice ranges will be truncated to the length of the text.

Argument Type Description Default
text Text The text to be sliced. -
from Int The index of the first grapheme cluster to include (1-indexed). 1
to Int The index of the last grapheme cluster to include (1-indexed). -1

Return: The text that spans the given grapheme cluster indices.

Example:

assert "hello".slice(2, 3) == "el"
assert "hello".slice(to=-2) == "hell"
assert "hello".slice(from=2) == "ello"

Text.split

Text.split : func(text: Text, delimiter: Text = "" -> [Text])

Splits the text into a list of substrings based on exact matches of a delimiter.

To split based on a set of delimiters, use Text.split_any(). If an empty text is given as the delimiter, then each split will be the graphical clusters of the text.

Argument Type Description Default
text Text The text to be split. -
delimiter Text The delimiter used to split the text. ""

Return: A list of subtexts resulting from the split.

Example:

assert "one,two,,three".split(",") == ["one", "two", "", "three"]
assert "abc".split() == ["a", "b", "c"]

Text.split_any

Text.split_any : func(text: Text, delimiters: Text = " $\t\r\n" -> [Text])

Splits the text into a list of substrings at one or more occurrences of a set of delimiter characters (grapheme clusters).

Splitting will occur on every place where one or more of the grapheme clusters in delimiters occurs. To split based on an exact delimiter, use Text.split().

Argument Type Description Default
text Text The text to be split. -
delimiters Text A text containing delimiters to use for splitting the text. " $\t\r\n"

Return: A list of subtexts resulting from the split.

Example:

assert "one, two,,three".split_any(", ") == ["one", "two", "three"]

Text.starts_with

Text.starts_with : func(text: Text, prefix: Text, remainder: &Text? = none -> Bool)

Checks if the Text starts with a literal prefix text.

Argument Type Description Default
text Text The text to be searched. -
prefix Text The literal prefix text to check for. -
remainder &Text? If non-none, this value will be set to the rest of the text after the prefix. If the prefix is not found, this value will be set to the original text. none

Return: yes if the text has the given prefix, no otherwise.

Example:

assert "hello world".starts_with("hello") == yes
remainder : Text
assert "hello world".starts_with("hello", &remainder) == yes
assert remainder == " world"

Text.title

Text.title : func(text: Text, language: Text = "C" -> Text)

Converts the text to title case (capitalizing the first letter of each word).

Argument Type Description Default
text Text The text to be converted to title case. -
language Text The ISO 639 language code for which casing rules to use. "C"

Return: The text in title case.

Example:

assert "amélie".title() == "Amélie"

# In Turkish, uppercase "i" is "İ"
assert "i".title(language="tr_TR") == "İ"

Text.to

Text.to : func(text: Text, last: Int -> Text)

Get a slice of the text, ending at the given position.

A negative index counts backwards from the end of the text, so -1 refers to the last cluster, -2 the second-to-last, etc. Slice ranges will be truncated to the length of the text.

Argument Type Description Default
text Text The text to be sliced. -
last Int The index of the last grapheme cluster to include (1-indexed). -

Return: The text up to and including the given grapheme cluster.

Example:

assert "goodbye".to(3) == "goo"
assert "goodbye".to(-2) == "goodby"

Text.translate

Text.translate : func(text: Text, translations: {Text:Text} -> Text)

Takes a table mapping target texts to their replacements and performs all the replacements in the table on the whole text. At each position, the first matching replacement is applied and the matching moves on to after the replacement text, so replacement text is not recursively modified. See Text.replace() for more information about replacement behavior.

Argument Type Description Default
text Text The text to be translated. -
translations {Text:Text} A table mapping from target text to its replacement. -

Return: The text with all occurrences of the targets replaced with their corresponding replacement text.

Example:

text := "A <tag> & an ampersand".translate({
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': "&quot",
    "'": "&#39;",
})
assert text == "A &lt;tag&gt; &amp; an ampersand"

Text.trim

Text.trim : func(text: Text, to_trim: Text = " $\t\r\n", left: Bool = yes, right: Bool = yes -> Text)

Trims the given characters (grapheme clusters) from the left and/or right side of the text.

Argument Type Description Default
text Text The text to be trimmed. -
to_trim Text The characters to remove from the left/right of the text. " $\t\r\n"
left Bool Whether or not to trim from the front of the text. yes
right Bool Whether or not to trim from the back of the text. yes

Return: The text without the trim characters at either end.

Example:

assert "   x y z    \n".trim() == "x y z"
assert "one,".trim(",") == "one"
assert "   xyz   ".trim(right=no) == "xyz   "

Text.upper

Text.upper : func(text: Text, language: Text = "C" -> Text)

Converts all characters in the text to uppercase.

Argument Type Description Default
text Text The text to be converted to uppercase. -
language Text The ISO 639 language code for which casing rules to use. "C"

Return: The uppercase version of the text.

Example:

assert "amélie".upper() == "AMÉLIE"

# In Turkish, uppercase "i" is "İ"
assert "i".upper(language="tr_TR") == "İ"

Text.utf16

Text.utf16 : func(text: Text -> [Int16])

Returns a list of Unicode code points for UTF16 encoding of the text.

Argument Type Description Default
text Text The text from which to extract Unicode code points. -

Return: A list of 16-bit integer Unicode code points ([Int16]).

Example:

assert "Åke".utf16() == [197, 107, 101]
assert "こんにちは世界".utf16() == [12371, 12435, 12395, 12385, 12399, 19990, 30028]

Text.utf32

Text.utf32 : func(text: Text -> [Int32])

Returns a list of Unicode code points for UTF32 encoding of the text.

Argument Type Description Default
text Text The text from which to extract Unicode code points. -

Return: A list of 32-bit integer Unicode code points ([Int32]).

Example:

assert "Amélie".utf32() == [65, 109, 233, 108, 105, 101]

Text.utf8

Text.utf8 : func(text: Text -> [Byte])

Converts a Text value to a list of bytes representing a UTF8 encoding of the text.

Argument Type Description Default
text Text The text to be converted to UTF8 bytes. -

Return: A list of bytes ([Byte]) representing the text in UTF8 encoding.

Example:

assert "Amélie".utf8() == [65, 109, 195, 169, 108, 105, 101]

Text.width

Text.width : func(text: Text -> Int)

Returns the display width of the text as seen in a terminal with appropriate font rendering. This is usually the same as the text's .length, but there are some characters like emojis that render wider than 1 cell.

This will not always be exactly accurate when your terminal's font rendering can't handle some unicode displaying correctly.

Argument Type Description Default
text Text The text whose length you want. -

Return: An integer representing the display width of the text.

Example:

assert "Amélie".width() == 6
assert "🤠".width() == 2

Text.without_prefix

Text.without_prefix : func(text: Text, prefix: Text -> Text)

Returns the text with a given prefix removed (if present).

Argument Type Description Default
text Text The text to remove the prefix from. -
prefix Text The prefix to remove. -

Return: A text without the given prefix (if present) or the unmodified text if the prefix is not present.

Example:

assert "foo:baz".without_prefix("foo:") == "baz"
assert "qux".without_prefix("foo:") == "qux"

Text.without_suffix

Text.without_suffix : func(text: Text, suffix: Text -> Text)

Returns the text with a given suffix removed (if present).

Argument Type Description Default
text Text The text to remove the suffix from. -
suffix Text The suffix to remove. -

Return: A text without the given suffix (if present) or the unmodified text if the suffix is not present.

Example:

assert "baz.foo".without_suffix(".foo") == "baz"
assert "qux".without_suffix(".foo") == "qux"

1 % API
3 # Builtins
4 ## USE_COLOR
6 ```tomo
7 USE_COLOR : Bool
8 ```
10 Whether or not the console prefers ANSI color escape sequences in the output.
12 ## ask
14 ```tomo
15 ask : func(prompt: Text, bold: Bool = yes, force_tty: Bool = yes -> Text?)
16 ```
18 Gets a line of user input text with a prompt.
20 When a program is receiving input from a pipe or writing its output to a pipe, this flag (which is enabled by default) forces the program to write the prompt to `/dev/tty` and read the input from `/dev/tty`, which circumvents the pipe. This means that `foo | ./tomo your-program | baz` will still show a visible prompt and read user input, despite the pipes. Setting this flag to `no` will mean that the prompt is written to `stdout` and input is read from `stdin`, even if those are pipes.
22 Argument | Type | Description | Default
23 ---------|------|-------------|---------
24 prompt | `Text` | The text to print as a prompt before getting the input. | -
25 bold | `Bool` | Whether or not to print make the prompt appear bold on a console. | `yes`
26 force_tty | `Bool` | Whether or not to force the use of /dev/tty. | `yes`
28 **Return:** A line of user input text without a trailing newline, or empty text if something went wrong (e.g. the user hit `Ctrl-D`).
31 **Example:**
32 ```tomo
33 assert ask("What's your name? ") == "Arthur Dent"
35 ```
36 ## at_cleanup
38 ```tomo
39 at_cleanup : func(fn: func() -> Void)
40 ```
42 Register a function that runs at cleanup time for Tomo programs. Cleanup time happens when a program exits (see `atexit()` in C), or immediately before printing error messages in a call to `fail()`. This allows for terminal cleanup so error messages can be visible as the program shuts down.
44 Use this API very carefully, because errors that occur during cleanup functions may make it extremely hard to figure out what's going on. Cleanup functions should be designed to not error under any circumstances.
46 Argument | Type | Description | Default
47 ---------|------|-------------|---------
48 fn | `func()` | A function to run at cleanup time. | -
50 **Return:** Nothing.
53 **Example:**
54 ```tomo
55 at_cleanup(func()
56 _ := (/tmp/file.txt).remove(ignore_missing=yes)
59 ```
60 ## exit
62 ```tomo
63 exit : func(message: Text? = none, status: Int32 = Int32(1) -> Abort)
64 ```
66 Exits the program with a given status and optionally prints a message.
68 Argument | Type | Description | Default
69 ---------|------|-------------|---------
70 message | `Text?` | If nonempty, this message will be printed (with a newline) before exiting. | `none`
71 status | `Int32` | The status code that the program with exit with. | `Int32(1)`
73 **Return:** This function never returns.
76 **Example:**
77 ```tomo
78 exit("Goodbye forever!", Int32(1))
80 ```
81 ## fail
83 ```tomo
84 fail : func(message: Text -> Abort)
85 ```
87 Prints a message to the console, aborts the program, and prints a stack trace.
89 Argument | Type | Description | Default
90 ---------|------|-------------|---------
91 message | `Text` | The error message to print. | -
93 **Return:** Nothing, aborts the program.
96 **Example:**
97 ```tomo
98 fail("Oh no!")
100 ```
101 ## getenv
103 ```tomo
104 getenv : func(name: Text -> Text?)
105 ```
107 Gets an environment variable.
109 Argument | Type | Description | Default
110 ---------|------|-------------|---------
111 name | `Text` | The name of the environment variable to get. | -
113 **Return:** If set, the environment variable's value, otherwise, `none`.
116 **Example:**
117 ```tomo
118 assert getenv("TERM") == "xterm-256color"
119 assert getenv("not_a_variable") == none
121 ```
122 ## print
124 ```tomo
125 print : func(text: Text, newline: Bool = yes -> Void)
126 ```
128 Prints a message to the console (alias for say()).
130 Argument | Type | Description | Default
131 ---------|------|-------------|---------
132 text | `Text` | The text to print. | -
133 newline | `Bool` | Whether or not to print a newline after the text. | `yes`
135 **Return:** Nothing.
138 **Example:**
139 ```tomo
140 print("Hello ", newline=no)
141 print("world!")
143 ```
144 ## say
146 ```tomo
147 say : func(text: Text, newline: Bool = yes -> Void)
148 ```
150 Prints a message to the console.
152 Argument | Type | Description | Default
153 ---------|------|-------------|---------
154 text | `Text` | The text to print. | -
155 newline | `Bool` | Whether or not to print a newline after the text. | `yes`
157 **Return:** Nothing.
160 **Example:**
161 ```tomo
162 say("Hello ", newline=no)
163 say("world!")
165 ```
166 ## setenv
168 ```tomo
169 setenv : func(name: Text, value: Text? -> Void)
170 ```
172 Sets an environment variable.
174 Argument | Type | Description | Default
175 ---------|------|-------------|---------
176 name | `Text` | The name of the environment variable to set. | -
177 value | `Text?` | The new value of the environment variable. If `none`, then the environment variable will be unset. | -
179 **Return:** Nothing.
182 **Example:**
183 ```tomo
184 setenv("FOOBAR", "xyz")
186 ```
187 ## sleep
189 ```tomo
190 sleep : func(seconds: Num -> Void)
191 ```
193 Pause execution for a given number of seconds.
195 Argument | Type | Description | Default
196 ---------|------|-------------|---------
197 seconds | `Num` | How many seconds to sleep for. | -
199 **Return:** Nothing.
202 **Example:**
203 ```tomo
204 sleep(1.5)
206 ```
208 # Bool
209 ## Bool.parse
211 ```tomo
212 Bool.parse : func(text: Text, remainder: &Text? = none -> Bool?)
213 ```
215 Converts a text representation of a boolean value into a boolean. Acceptable boolean values are case-insensitive variations of `yes`/`no`, `y`/`n`, `true`/`false`, `on`/`off`.
217 Argument | Type | Description | Default
218 ---------|------|-------------|---------
219 text | `Text` | The string containing the boolean value. | -
220 remainder | `&Text?` | If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. | `none`
222 **Return:** `yes` if the string matches a recognized truthy boolean value; otherwise return `no`.
225 **Example:**
226 ```tomo
227 assert Bool.parse("yes") == yes
228 assert Bool.parse("no") == no
229 assert Bool.parse("???") == none
231 assert Bool.parse("yesJUNK") == none
232 remainder : Text
233 assert Bool.parse("yesJUNK", &remainder) == yes
234 assert remainder == "JUNK"
236 ```
238 # Byte
239 ## Byte.get_bit
241 ```tomo
242 Byte.get_bit : func(i: Byte, bit_index: Int -> Bool)
243 ```
245 In the binary representation of a byte, check whether a given bit index is set to 1 or not.
247 The bit index must be between 1-8 or a runtime error will be produced.
249 Argument | Type | Description | Default
250 ---------|------|-------------|---------
251 i | `Byte` | The byte whose bits are being inspected. | -
252 bit_index | `Int` | The index of the bit to check (1-indexed, range 1-8). | -
254 **Return:** Whether or not the given bit index is set to 1 in the byte.
257 **Example:**
258 ```tomo
259 assert Byte(6).get_bit(1) == no
260 assert Byte(6).get_bit(2) == yes
261 assert Byte(6).get_bit(3) == yes
262 assert Byte(6).get_bit(4) == no
264 ```
265 ## Byte.hex
267 ```tomo
268 Byte.hex : func(byte: Byte, uppercase: Bool = yes, prefix: Bool = no -> Text)
269 ```
271 Convert a byte to a hexidecimal text representation.
273 Argument | Type | Description | Default
274 ---------|------|-------------|---------
275 byte | `Byte` | The byte to convert to hex. | -
276 uppercase | `Bool` | Whether or not to use uppercase hexidecimal letters. | `yes`
277 prefix | `Bool` | Whether or not to prepend a `0x` prefix. | `no`
279 **Return:** The byte as a hexidecimal text.
282 **Example:**
283 ```tomo
284 assert Byte(18).hex(prefix=yes) == "0x12"
286 ```
287 ## Byte.is_between
289 ```tomo
290 Byte.is_between : func(x: Byte, low: Byte, high: Byte -> Bool)
291 ```
293 Determines if an integer is between two numbers (inclusive).
295 Argument | Type | Description | Default
296 ---------|------|-------------|---------
297 x | `Byte` | The integer to be checked. | -
298 low | `Byte` | One end of the range to check (inclusive); | -
299 high | `Byte` | The other end of the range to check (inclusive); | -
301 **Return:** `yes` if `a <= x and x <= b` or `b <= x and x <= a`, otherwise `no`
304 **Example:**
305 ```tomo
306 assert Byte(7).is_between(1, 10) == yes
307 assert Byte(7).is_between(10, 1) == yes
308 assert Byte(7).is_between(100, 200) == no
309 assert Byte(7).is_between(1, 7) == yes
311 ```
312 ## Byte.parse
314 ```tomo
315 Byte.parse : func(text: Text, base: Int? = none, remainder: &Text? = none -> Byte?)
316 ```
318 Parse a byte literal from text.
320 Argument | Type | Description | Default
321 ---------|------|-------------|---------
322 text | `Text` | The text to parse. | -
323 base | `Int?` | The numeric base to use when parsing the byte. If unspecified, the byte's base will be inferred from the text prefix. After any "+" or "-" sign, if the text begins with "0x", the base will be assumed to be 16, "0o" will assume base 8, "0b" will assume base 2, otherwise the base will be assumed to be 10. | `none`
324 remainder | `&Text?` | If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. | `none`
326 **Return:** The byte parsed from the text, if successful, otherwise `none`.
329 **Example:**
330 ```tomo
331 assert Byte.parse("5") == Byte(5)
332 assert Byte.parse("asdf") == none
333 assert Byte.parse("123xyz") == none
335 remainder : Text
336 assert Byte.parse("123xyz", remainder=&remainder) == Byte(123)
337 assert remainder == "xyz"
339 ```
340 ## Byte.to
342 ```tomo
343 Byte.to : func(first: Byte, last: Byte, step: Int8? = none -> func(->Byte?))
344 ```
346 Returns an iterator function that iterates over the range of bytes specified.
348 Argument | Type | Description | Default
349 ---------|------|-------------|---------
350 first | `Byte` | The starting value of the range. | -
351 last | `Byte` | The ending value of the range. | -
352 step | `Int8?` | An optional step size to use. If unspecified or `none`, the step will be inferred to be `+1` if `last >= first`, otherwise `-1`. | `none`
354 **Return:** An iterator function that returns each byte in the given range (inclusive).
357 **Example:**
358 ```tomo
359 iter := Byte(2).to(4)
360 assert iter() == Byte(2)
361 assert iter() == Byte(3)
362 assert iter() == Byte(4)
363 assert iter() == none
365 assert [x for x in Byte(2).to(5)] == [Byte(2), Byte(3), Byte(4), Byte(5)]
366 assert [x for x in Byte(5).to(2)] == [Byte(5), Byte(4), Byte(3), Byte(2)]
367 assert [x for x in Byte(2).to(5, step=2)] == [Byte(2), Byte(4)]
369 ```
371 # CString
372 ## CString.as_text
374 ```tomo
375 CString.as_text : func(str: CString -> Text)
376 ```
378 Convert a C string to Text.
380 Argument | Type | Description | Default
381 ---------|------|-------------|---------
382 str | `CString` | The C string. | -
384 **Return:** The C string as a Text.
387 **Example:**
388 ```tomo
389 assert CString("Hello").as_text() == "Hello"
391 ```
392 ## CString.join
394 ```tomo
395 CString.join : func(glue: CString, pieces: [CString] -> CString)
396 ```
398 Join a list of C strings together with a separator.
400 Argument | Type | Description | Default
401 ---------|------|-------------|---------
402 glue | `CString` | The C joiner used to between elements. | -
403 pieces | `[CString]` | A list of C strings to join. | -
405 **Return:** A C string of the joined together bits.
408 **Example:**
409 ```tomo
410 assert CString(",").join([CString("a"), CString("b")]) == CString("a,b")
412 ```
414 # Int
415 ## Int.abs
417 ```tomo
418 Int.abs : func(x: Int -> Int)
419 ```
421 Calculates the absolute value of an integer.
423 Argument | Type | Description | Default
424 ---------|------|-------------|---------
425 x | `Int` | The integer whose absolute value is to be calculated. | -
427 **Return:** The absolute value of `x`.
430 **Example:**
431 ```tomo
432 assert (-10).abs() == 10
434 ```
435 ## Int.choose
437 ```tomo
438 Int.choose : func(n: Int, k: Int -> Int)
439 ```
441 Computes the binomial coefficient of the given numbers (the equivalent of `n` choose `k` in combinatorics). This is equal to `n.factorial()/(k.factorial() * (n-k).factorial())`.
443 Argument | Type | Description | Default
444 ---------|------|-------------|---------
445 n | `Int` | The number of things to choose from. | -
446 k | `Int` | The number of things to be chosen. | -
448 **Return:** The binomial coefficient, equivalent to the number of ways to uniquely choose `k` objects from among `n` objects, ignoring order.
451 **Example:**
452 ```tomo
453 assert 4.choose(2) == 6
455 ```
456 ## Int.clamped
458 ```tomo
459 Int.clamped : func(x: Int, low: Int, high: Int -> Int)
460 ```
462 Returns the given number clamped between two values so that it is within that range.
464 Argument | Type | Description | Default
465 ---------|------|-------------|---------
466 x | `Int` | The integer to clamp. | -
467 low | `Int` | The lowest value the result can take. | -
468 high | `Int` | The highest value the result can take. | -
470 **Return:** The first argument clamped between the other two arguments.
473 **Example:**
474 ```tomo
475 assert 2.clamped(5, 10) == 5
477 ```
478 ## Int.factorial
480 ```tomo
481 Int.factorial : func(n: Int -> Text)
482 ```
484 Computes the factorial of an integer.
486 Argument | Type | Description | Default
487 ---------|------|-------------|---------
488 n | `Int` | The integer to compute the factorial of. | -
490 **Return:** The factorial of the given integer.
493 **Example:**
494 ```tomo
495 assert 10.factorial() == 3628800
497 ```
498 ## Int.get_bit
500 ```tomo
501 Int.get_bit : func(i: Int, bit_index: Int -> Bool)
502 ```
504 In the binary representation of an integer, check whether a given bit index is set to 1 or not.
506 For fixed-size integers, the bit index must be between 1 and the number of bits in that integer (i.e. 1-64 for `Int64`). For `Int`, the bit index must be between 1 and `Int64.max`. Values outside this range will produce a runtime error.
508 Argument | Type | Description | Default
509 ---------|------|-------------|---------
510 i | `Int` | The integer whose bits are being inspected. | -
511 bit_index | `Int` | The index of the bit to check (1-indexed). | -
513 **Return:** Whether or not the given bit index is set to 1 in the binary representation of the integer.
516 **Example:**
517 ```tomo
518 assert 6.get_bit(1) == no
519 assert 6.get_bit(2) == yes
520 assert 6.get_bit(3) == yes
521 assert 6.get_bit(4) == no
523 ```
524 ## Int.hex
526 ```tomo
527 Int.hex : func(i: Int, digits: Int = 0, uppercase: Bool = yes, prefix: Bool = yes -> Text)
528 ```
530 Converts an integer to its hexadecimal representation.
532 Argument | Type | Description | Default
533 ---------|------|-------------|---------
534 i | `Int` | The integer to be converted. | -
535 digits | `Int` | The minimum number of digits in the output string. | `0`
536 uppercase | `Bool` | Whether to use uppercase letters for hexadecimal digits. | `yes`
537 prefix | `Bool` | Whether to include a "0x" prefix. | `yes`
539 **Return:** The hexadecimal string representation of the integer.
542 **Example:**
543 ```tomo
544 assert 255.hex(digits=4, uppercase=yes, prefix=yes) == "0x00FF"
546 ```
547 ## Int.is_between
549 ```tomo
550 Int.is_between : func(x: Int, a: Int, b: Int -> Bool)
551 ```
553 Determines if an integer is between two numbers (inclusive).
555 Argument | Type | Description | Default
556 ---------|------|-------------|---------
557 x | `Int` | The integer to be checked. | -
558 a | `Int` | One end of the range to check (inclusive). | -
559 b | `Int` | The other end of the range to check (inclusive). | -
561 **Return:** `yes` if `a <= x and x <= b` or `a >= x and x >= b`, otherwise `no`
564 **Example:**
565 ```tomo
566 assert 7.is_between(1, 10) == yes
567 assert 7.is_between(10, 1) == yes
568 assert 7.is_between(100, 200) == no
569 assert 7.is_between(1, 7) == yes
571 ```
572 ## Int.is_prime
574 ```tomo
575 Int.is_prime : func(x: Int, reps: Int = 50 -> Bool)
576 ```
578 Determines if an integer is a prime number.
580 This function is _probabilistic_. With the default arguments, the chances of getting an incorrect answer are astronomically small (on the order of 10^(-30)). See [the GNU MP docs](https://gmplib.org/manual/Number-Theoretic-Functions#index-mpz_005fprobab_005fprime_005fp) for more details.
582 Argument | Type | Description | Default
583 ---------|------|-------------|---------
584 x | `Int` | The integer to be checked. | -
585 reps | `Int` | The number of repetitions for primality tests. | `50`
587 **Return:** `yes` if `x` is a prime number, `no` otherwise.
590 **Example:**
591 ```tomo
592 assert 7.is_prime() == yes
593 assert 6.is_prime() == no
595 ```
596 ## Int.next_prime
598 ```tomo
599 Int.next_prime : func(x: Int -> Int)
600 ```
602 Finds the next prime number greater than the given integer.
604 This function is _probabilistic_, but the chances of getting an incorrect answer are astronomically small (on the order of 10^(-30)). See [the GNU MP docs](https://gmplib.org/manual/Number-Theoretic-Functions#index-mpz_005fprobab_005fprime_005fp) for more details.
606 Argument | Type | Description | Default
607 ---------|------|-------------|---------
608 x | `Int` | The integer after which to find the next prime. | -
610 **Return:** The next prime number greater than `x`.
613 **Example:**
614 ```tomo
615 assert 11.next_prime() == 13
617 ```
618 ## Int.octal
620 ```tomo
621 Int.octal : func(i: Int, digits: Int = 0, prefix: Bool = yes -> Text)
622 ```
624 Converts an integer to its octal representation.
626 Argument | Type | Description | Default
627 ---------|------|-------------|---------
628 i | `Int` | The integer to be converted. | -
629 digits | `Int` | The minimum number of digits in the output string. | `0`
630 prefix | `Bool` | Whether to include a "0o" prefix. | `yes`
632 **Return:** The octal string representation of the integer.
635 **Example:**
636 ```tomo
637 assert 64.octal(digits=4, prefix=yes) == "0o0100"
639 ```
640 ## Int.onward
642 ```tomo
643 Int.onward : func(first: Int, step: Int = 1 -> Text)
644 ```
646 Return an iterator that counts infinitely from the starting integer (with an optional step size).
648 Argument | Type | Description | Default
649 ---------|------|-------------|---------
650 first | `Int` | The starting integer. | -
651 step | `Int` | The increment step size. | `1`
653 **Return:** An iterator function that counts onward from the starting integer.
656 **Example:**
657 ```tomo
658 nums : &[Int] = &[]
659 for i in 5.onward()
660 nums.insert(i)
661 stop if i == 10
662 assert nums[] == [5, 6, 7, 8, 9, 10]
664 ```
665 ## Int.parse
667 ```tomo
668 Int.parse : func(text: Text, base: Int? = none, remainder: &Text? = none -> Int?)
669 ```
671 Converts a text representation of an integer into an integer.
673 Argument | Type | Description | Default
674 ---------|------|-------------|---------
675 text | `Text` | The text containing the integer. | -
676 base | `Int?` | The numeric base to use when parsing the integer. If unspecified, the integer's base will be inferred from the text prefix. After any "+" or "-" sign, if the text begins with "0x", the base will be assumed to be 16, "0o" will assume base 8, "0b" will assume base 2, otherwise the base will be assumed to be 10. | `none`
677 remainder | `&Text?` | If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. | `none`
679 **Return:** The integer represented by the text. If the given text contains a value outside of the representable range or if the entire text can't be parsed as an integer, `none` will be returned.
682 **Example:**
683 ```tomo
684 assert Int.parse("123") == 123
685 assert Int.parse("0xFF") == 255
686 assert Int.parse("123xyz") == none
687 remainder : Text
688 assert Int.parse("123xyz", remainder=&remainder) == 123
689 assert remainder == "xyz"
691 # Can't parse:
692 assert Int.parse("asdf") == none
694 # Outside valid range:
695 assert Int8.parse("9999999") == none
697 # Explicitly specifying base:
698 assert Int.parse("10", base=16) == 16
700 ```
701 ## Int.sqrt
703 ```tomo
704 Int.sqrt : func(x: Int -> Int)
705 ```
707 Calculates the nearest square root of an integer.
709 Argument | Type | Description | Default
710 ---------|------|-------------|---------
711 x | `Int` | The integer whose square root is to be calculated. | -
713 **Return:** The integer part of the square root of `x`.
716 **Example:**
717 ```tomo
718 assert 16.sqrt() == 4
719 assert 17.sqrt() == 4
721 ```
722 ## Int.to
724 ```tomo
725 Int.to : func(first: Int, last: Int, step: Int? = none -> func(->Int?))
726 ```
728 Returns an iterator function that iterates over the range of numbers specified.
730 Argument | Type | Description | Default
731 ---------|------|-------------|---------
732 first | `Int` | The starting value of the range. | -
733 last | `Int` | The ending value of the range. | -
734 step | `Int?` | An optional step size to use. If unspecified or `none`, the step will be inferred to be `+1` if `last >= first`, otherwise `-1`. | `none`
736 **Return:** An iterator function that returns each integer in the given range (inclusive).
739 **Example:**
740 ```tomo
741 iter := 2.to(5)
742 assert iter() == 2
743 assert iter() == 3
744 assert iter() == 4
745 assert iter() == 5
746 assert iter() == none
748 assert [x for x in 2.to(5)] == [2, 3, 4, 5]
749 assert [x for x in 5.to(2)] == [5, 4, 3, 2]
750 assert [x for x in 2.to(5, step=2)] == [2, 4]
752 ```
754 # List
755 ## List.binary_search
757 ```tomo
758 List.binary_search : func(list: [T], by: func(x,y:&T->Int32) = T.compare -> Int)
759 ```
761 Performs a binary search on a sorted list.
763 Argument | Type | Description | Default
764 ---------|------|-------------|---------
765 list | `[T]` | The sorted list to search. | -
766 by | `func(x,y:&T->Int32)` | The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. | `T.compare`
768 **Return:** Assuming the input list is sorted according to the given comparison function, return the index where the given item would be inserted to maintain the sorted order. That is, if the item is found, return its index, otherwise return the place where it would be found if it were inserted and the list were sorted.
771 **Example:**
772 ```tomo
773 assert [1, 3, 5, 7, 9].binary_search(5) == 3
774 assert [1, 3, 5, 7, 9].binary_search(-999) == 1
775 assert [1, 3, 5, 7, 9].binary_search(999) == 6
777 ```
778 ## List.by
780 ```tomo
781 List.by : func(list: [T], step: Int -> [T])
782 ```
784 Creates a new list with elements spaced by the specified step value.
786 Argument | Type | Description | Default
787 ---------|------|-------------|---------
788 list | `[T]` | The original list. | -
789 step | `Int` | The step value for selecting elements. | -
791 **Return:** A new list with every `step`-th element from the original list.
794 **Example:**
795 ```tomo
796 assert [1, 2, 3, 4, 5, 6].by(2) == [1, 3, 5]
798 ```
799 ## List.clear
801 ```tomo
802 List.clear : func(list: @[T] -> Void)
803 ```
805 Clears all elements from the list.
807 Argument | Type | Description | Default
808 ---------|------|-------------|---------
809 list | `@[T]` | The mutable reference to the list to be cleared. | -
811 **Return:** Nothing.
814 **Example:**
815 ```tomo
816 list := &[10, 20]
817 list.clear()
818 assert list[] == []
820 ```
821 ## List.counts
823 ```tomo
824 List.counts : func(list: [T] -> {T=Int})
825 ```
827 Counts the occurrences of each element in the list.
829 Argument | Type | Description | Default
830 ---------|------|-------------|---------
831 list | `[T]` | The list to count elements in. | -
833 **Return:** A table mapping each element to its count.
836 **Example:**
837 ```tomo
838 assert [10, 20, 30, 30, 30].counts() == {10:1, 20:1, 30:3}
840 ```
841 ## List.find
843 ```tomo
844 List.find : func(list: [T], target: T -> Int?)
845 ```
847 Finds the index of the first occurrence of an element (if any).
849 Argument | Type | Description | Default
850 ---------|------|-------------|---------
851 list | `[T]` | The list to search through. | -
852 target | `T` | The item to search for. | -
854 **Return:** The index of the first occurrence or `none` if not found.
857 **Example:**
858 ```tomo
859 assert [10, 20, 30, 40, 50].find(20) == 2
860 assert [10, 20, 30, 40, 50].find(9999) == none
862 ```
863 ## List.from
865 ```tomo
866 List.from : func(list: [T], first: Int -> [T])
867 ```
869 Returns a slice of the list starting from a specified index.
871 Argument | Type | Description | Default
872 ---------|------|-------------|---------
873 list | `[T]` | The original list. | -
874 first | `Int` | The index to start from. | -
876 **Return:** A new list starting from the specified index.
879 **Example:**
880 ```tomo
881 assert [10, 20, 30, 40, 50].from(3) == [30, 40, 50]
883 ```
884 ## List.has
886 ```tomo
887 List.has : func(list: [T], target: T -> Bool)
888 ```
890 Checks if the list has an element.
892 Argument | Type | Description | Default
893 ---------|------|-------------|---------
894 list | `[T]` | The list to check. | -
895 target | `T` | The element to check for. | -
897 **Return:** `yes` if the list has the element, `no` otherwise.
900 **Example:**
901 ```tomo
902 assert [10, 20, 30].has(20) == yes
904 ```
905 ## List.heap_pop
907 ```tomo
908 List.heap_pop : func(list: @[T], by: func(x,y:&T->Int32) = T.compare -> T?)
909 ```
911 Removes and returns the top element of a heap or `none` if the list is empty. By default, this is the *minimum* value in the heap.
913 Argument | Type | Description | Default
914 ---------|------|-------------|---------
915 list | `@[T]` | The mutable reference to the heap. | -
916 by | `func(x,y:&T->Int32)` | The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. | `T.compare`
918 **Return:** The removed top element of the heap or `none` if the list is empty.
921 **Example:**
922 ```tomo
923 my_heap := &[30, 10, 20]
924 my_heap.heapify()
925 assert my_heap.heap_pop() == 10
927 ```
928 ## List.heap_push
930 ```tomo
931 List.heap_push : func(list: @[T], item: T, by = T.compare -> Void)
932 ```
934 Adds an element to the heap and maintains the heap property. By default, this is a *minimum* heap.
936 Argument | Type | Description | Default
937 ---------|------|-------------|---------
938 list | `@[T]` | The mutable reference to the heap. | -
939 item | `T` | The item to be added. | -
940 by | `` | The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. | `T.compare`
942 **Return:** Nothing.
945 **Example:**
946 ```tomo
947 my_heap : &[Int]
948 my_heap.heap_push(10)
949 assert my_heap.heap_pop() == 10
951 ```
952 ## List.heapify
954 ```tomo
955 List.heapify : func(list: @[T], by: func(x,y:&T->Int32) = T.compare -> Void)
956 ```
958 Converts a list into a heap.
960 Argument | Type | Description | Default
961 ---------|------|-------------|---------
962 list | `@[T]` | The mutable reference to the list to be heapified. | -
963 by | `func(x,y:&T->Int32)` | The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. | `T.compare`
965 **Return:** Nothing.
968 **Example:**
969 ```tomo
970 my_heap := &[30, 10, 20]
971 my_heap.heapify()
973 ```
974 ## List.insert
976 ```tomo
977 List.insert : func(list: @[T], item: T, at: Int = 0 -> Void)
978 ```
980 Inserts an element at a specified position in the list.
982 Since indices are 1-indexed and negative indices mean "starting from the back", an index of `0` means "after the last item".
984 Argument | Type | Description | Default
985 ---------|------|-------------|---------
986 list | `@[T]` | The mutable reference to the list. | -
987 item | `T` | The item to be inserted. | -
988 at | `Int` | The index at which to insert the item. | `0`
990 **Return:** Nothing.
993 **Example:**
994 ```tomo
995 list := &[10, 20]
996 list.insert(30)
997 assert list == [10, 20, 30]
999 list.insert(999, at=2)
1000 assert list == [10, 999, 20, 30]
1002 ```
1003 ## List.insert_all
1005 ```tomo
1006 List.insert_all : func(list: @[T], items: [T], at: Int = 0 -> Void)
1007 ```
1009 Inserts a list of items at a specified position in the list.
1011 Since indices are 1-indexed and negative indices mean "starting from the back", an index of `0` means "after the last item".
1013 Argument | Type | Description | Default
1014 ---------|------|-------------|---------
1015 list | `@[T]` | The mutable reference to the list. | -
1016 items | `[T]` | The items to be inserted. | -
1017 at | `Int` | The index at which to insert the item. | `0`
1019 **Return:** Nothing.
1022 **Example:**
1023 ```tomo
1024 list := &[10, 20]
1025 list.insert_all([30, 40])
1026 assert list == [10, 20, 30, 40]
1028 list.insert_all([99, 100], at=2)
1029 assert list == [10, 99, 100, 20, 30, 40]
1031 ```
1032 ## List.pop
1034 ```tomo
1035 List.pop : func(list: &[T], index: Int = -1 -> T?)
1036 ```
1038 Removes and returns an item from the list. If the given index is present in the list, the item at that index will be removed and the list will become one element shorter.
1040 Since negative indices are counted from the back, the default behavior is to pop the last value.
1042 Argument | Type | Description | Default
1043 ---------|------|-------------|---------
1044 list | `&[T]` | The list to remove an item from. | -
1045 index | `Int` | The index from which to remove the item. | `-1`
1047 **Return:** `none` if the list is empty or the given index does not exist in the list, otherwise the item at the given index.
1050 **Example:**
1051 ```tomo
1052 list := &[10, 20, 30, 40]
1054 assert list.pop() == 40
1055 assert list[] == [10, 20, 30]
1057 assert list.pop(index=2) == 20
1058 assert list[] == [10, 30]
1060 ```
1061 ## List.random
1063 ```tomo
1064 List.random : func(list: [T], random: func(min,max:Int64->Int64)? = none -> T?)
1065 ```
1067 Selects a random element from the list.
1069 Argument | Type | Description | Default
1070 ---------|------|-------------|---------
1071 list | `[T]` | The list from which to select a random element. | -
1072 random | `func(min,max:Int64->Int64)?` | If provided, this function will be used to get a random index in the list. Returned values must be between `min` and `max` (inclusive). (Used for deterministic pseudorandom number generation) | `none`
1074 **Return:** A random element from the list or `none` if the list is empty.
1077 **Example:**
1078 ```tomo
1079 nums := [10, 20, 30]
1080 pick := nums.random()!
1081 assert nums.has(pick)
1082 empty : [Int]
1083 assert empty.random() == none
1085 ```
1086 ## List.remove_at
1088 ```tomo
1089 List.remove_at : func(list: @[T], at: Int = -1, count: Int = 1 -> Void)
1090 ```
1092 Removes elements from the list starting at a specified index.
1094 Since negative indices are counted from the back, the default behavior is to remove the last item.
1096 Argument | Type | Description | Default
1097 ---------|------|-------------|---------
1098 list | `@[T]` | The mutable reference to the list. | -
1099 at | `Int` | The index at which to start removing elements. | `-1`
1100 count | `Int` | The number of elements to remove. | `1`
1102 **Return:** Nothing.
1105 **Example:**
1106 ```tomo
1107 list := &[10, 20, 30, 40, 50]
1108 list.remove_at(2)
1109 assert list == [10, 30, 40, 50]
1111 list.remove_at(2, count=2)
1112 assert list == [10, 50]
1114 ```
1115 ## List.remove_item
1117 ```tomo
1118 List.remove_item : func(list: @[T], item: T, max_count: Int = -1 -> Void)
1119 ```
1121 Removes all occurrences of a specified item from the list.
1123 A negative `max_count` means "remove all occurrences".
1125 Argument | Type | Description | Default
1126 ---------|------|-------------|---------
1127 list | `@[T]` | The mutable reference to the list. | -
1128 item | `T` | The item to be removed. | -
1129 max_count | `Int` | The maximum number of occurrences to remove. | `-1`
1131 **Return:** Nothing.
1134 **Example:**
1135 ```tomo
1136 list := &[10, 20, 10, 20, 30]
1137 list.remove_item(10)
1138 assert list == [20, 20, 30]
1140 list.remove_item(20, max_count=1)
1141 assert list == [20, 30]
1143 ```
1144 ## List.reversed
1146 ```tomo
1147 List.reversed : func(list: [T] -> [T])
1148 ```
1150 Returns a reversed slice of the list.
1152 Argument | Type | Description | Default
1153 ---------|------|-------------|---------
1154 list | `[T]` | The list to be reversed. | -
1156 **Return:** A slice of the list with elements in reverse order.
1159 **Example:**
1160 ```tomo
1161 assert [10, 20, 30].reversed() == [30, 20, 10]
1163 ```
1164 ## List.sample
1166 ```tomo
1167 List.sample : func(list: [T], count: Int, weights: [Num]? = none, random: func(->Num)? = none -> [T])
1168 ```
1170 Selects a sample of elements from the list, optionally with weighted probabilities.
1172 Errors will be raised if any of the following conditions occurs: - The given list has no elements and `count >= 1` - `count < 0` (negative count) - The number of weights provided doesn't match the length of the list. - Any weight in the weights list is negative, infinite, or `NaN` - The sum of the given weights is zero (zero probability for every element).
1174 Argument | Type | Description | Default
1175 ---------|------|-------------|---------
1176 list | `[T]` | The list to sample from. | -
1177 count | `Int` | The number of elements to sample. | -
1178 weights | `[Num]?` | The probability weights for each element in the list. These values do not need to add up to any particular number, they are relative weights. If no weights are given, elements will be sampled with uniform probability. | `none`
1179 random | `func(->Num)?` | If provided, this function will be used to get random values for sampling the list. The provided function should return random numbers between `0.0` (inclusive) and `1.0` (exclusive). (Used for deterministic pseudorandom number generation) | `none`
1181 **Return:** A list of sampled elements from the list.
1184 **Example:**
1185 ```tomo
1186 _ := [10, 20, 30].sample(2, weights=[90%, 5%, 5%]) # E.g. [10, 10]
1188 ```
1189 ## List.shuffle
1191 ```tomo
1192 List.shuffle : func(list: @[T], random: func(min,max:Int64->Int64)? = none -> Void)
1193 ```
1195 Shuffles the elements of the list in place.
1197 Argument | Type | Description | Default
1198 ---------|------|-------------|---------
1199 list | `@[T]` | The mutable reference to the list to be shuffled. | -
1200 random | `func(min,max:Int64->Int64)?` | If provided, this function will be used to get a random index in the list. Returned values must be between `min` and `max` (inclusive). (Used for deterministic pseudorandom number generation) | `none`
1202 **Return:** Nothing.
1205 **Example:**
1206 ```tomo
1207 nums := &[10, 20, 30, 40]
1208 nums.shuffle()
1209 # E.g. [20, 40, 10, 30]
1211 ```
1212 ## List.shuffled
1214 ```tomo
1215 List.shuffled : func(list: [T], random: func(min,max:Int64->Int64)? = none -> [T])
1216 ```
1218 Creates a new list with elements shuffled.
1220 Argument | Type | Description | Default
1221 ---------|------|-------------|---------
1222 list | `[T]` | The list to be shuffled. | -
1223 random | `func(min,max:Int64->Int64)?` | If provided, this function will be used to get a random index in the list. Returned values must be between `min` and `max` (inclusive). (Used for deterministic pseudorandom number generation) | `none`
1225 **Return:** A new list with shuffled elements.
1228 **Example:**
1229 ```tomo
1230 nums := [10, 20, 30, 40]
1231 _ := nums.shuffled()
1232 # E.g. [20, 40, 10, 30]
1234 ```
1235 ## List.slice
1237 ```tomo
1238 List.slice : func(list: [T], from: Int, to: Int -> [T])
1239 ```
1241 Returns a slice of the list spanning the given indices (inclusive).
1243 Argument | Type | Description | Default
1244 ---------|------|-------------|---------
1245 list | `[T]` | The original list. | -
1246 from | `Int` | The first index to include. | -
1247 to | `Int` | The last index to include. | -
1249 **Return:** A new list spanning the given indices. Note: negative indices are counted from the back of the list, so `-1` refers to the last element, `-2` the second-to-last, and so on.
1252 **Example:**
1253 ```tomo
1254 assert [10, 20, 30, 40, 50].slice(2, 4) == [20, 30, 40]
1255 assert [10, 20, 30, 40, 50].slice(-3, -2) == [30, 40]
1257 ```
1258 ## List.sort
1260 ```tomo
1261 List.sort : func(list: @[T], by = T.compare -> Void)
1262 ```
1264 Sorts the elements of the list in place in ascending order (small to large).
1266 Argument | Type | Description | Default
1267 ---------|------|-------------|---------
1268 list | `@[T]` | The mutable reference to the list to be sorted. | -
1269 by | `` | The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. | `T.compare`
1271 **Return:** Nothing.
1274 **Example:**
1275 ```tomo
1276 list := &[40, 10, -30, 20]
1277 list.sort()
1278 assert list == [-30, 10, 20, 40]
1280 list.sort(func(a,b:&Int) a.abs() <> b.abs())
1281 assert list == [10, 20, -30, 40]
1283 ```
1284 ## List.sorted
1286 ```tomo
1287 List.sorted : func(list: [T], by = T.compare -> [T])
1288 ```
1290 Creates a new list with elements sorted.
1292 Argument | Type | Description | Default
1293 ---------|------|-------------|---------
1294 list | `[T]` | The list to be sorted. | -
1295 by | `` | The comparison function used to determine order. If not specified, the default comparison function for the item type will be used. | `T.compare`
1297 **Return:** A new list with sorted elements.
1300 **Example:**
1301 ```tomo
1302 assert [40, 10, -30, 20].sorted() == [-30, 10, 20, 40]
1303 assert [40, 10, -30, 20].sorted(
1304 func(a,b:&Int) a.abs() <> b.abs()
1305 ) == [10, 20, -30, 40]
1307 ```
1308 ## List.to
1310 ```tomo
1311 List.to : func(list: [T], last: Int -> [T])
1312 ```
1314 Returns a slice of the list from the start of the original list up to a specified index (inclusive).
1316 Argument | Type | Description | Default
1317 ---------|------|-------------|---------
1318 list | `[T]` | The original list. | -
1319 last | `Int` | The index up to which elements should be included. | -
1321 **Return:** A new list containing elements from the start up to the specified index.
1324 **Example:**
1325 ```tomo
1326 assert [10, 20, 30, 40, 50].to(3) == [10, 20, 30]
1327 assert [10, 20, 30, 40, 50].to(-2) == [10, 20, 30, 40]
1329 ```
1330 ## List.unique
1332 ```tomo
1333 List.unique : func(list: [T] -> {T})
1334 ```
1336 Returns a set of the unique elements of the list.
1338 Argument | Type | Description | Default
1339 ---------|------|-------------|---------
1340 list | `[T]` | The list to process. | -
1342 **Return:** A set of the unique elements from the list.
1345 **Example:**
1346 ```tomo
1347 assert [10, 20, 10, 10, 30].unique() == {10, 20, 30}
1349 ```
1350 ## List.where
1352 ```tomo
1353 List.where : func(list: [T], predicate: func(item:&T -> Bool) -> Int)
1354 ```
1356 Find the index of the first item that matches a predicate function (if any).
1358 Argument | Type | Description | Default
1359 ---------|------|-------------|---------
1360 list | `[T]` | The list to search through. | -
1361 predicate | `func(item:&T -> Bool)` | A function that returns `yes` if the item's index should be returned or `no` if it should not. | -
1363 **Return:** Returns the index of the first item where the predicate is true or `none` if no item matches.
1366 **Example:**
1367 ```tomo
1368 assert ["BC", "ABC", "CD"].where(func(t:&Text) t.starts_with("A")) == 2
1369 assert ["BC", "ABC", "CD"].where(func(t:&Text) t.starts_with("X")) == none
1371 ```
1373 # Num
1374 ## Num.1_PI
1376 ```tomo
1377 Num.1_PI : Num
1378 ```
1380 The constant $\frac{1}{\pi}$.
1382 ## Num.2_PI
1384 ```tomo
1385 Num.2_PI : Num
1386 ```
1388 The constant $2 \times \pi$.
1390 ## Num.2_SQRTPI
1392 ```tomo
1393 Num.2_SQRTPI : Num
1394 ```
1396 The constant $2 \times \sqrt{\pi}$.
1398 ## Num.E
1400 ```tomo
1401 Num.E : Num
1402 ```
1404 The base of the natural logarithm ($e$).
1406 ## Num.INF
1408 ```tomo
1409 Num.INF : Num
1410 ```
1412 Positive infinity.
1414 ## Num.LN10
1416 ```tomo
1417 Num.LN10 : Num
1418 ```
1420 The natural logarithm of 10.
1422 ## Num.LN2
1424 ```tomo
1425 Num.LN2 : Num
1426 ```
1428 The natural logarithm of 2.
1430 ## Num.LOG2E
1432 ```tomo
1433 Num.LOG2E : Num
1434 ```
1436 The base 2 logarithm of $e$
1438 ## Num.PI
1440 ```tomo
1441 Num.PI : Num
1442 ```
1444 Pi ($\pi$).
1446 ## Num.PI_2
1448 ```tomo
1449 Num.PI_2 : Num
1450 ```
1452 $\frac{\pi}{2}$
1454 ## Num.PI_4
1456 ```tomo
1457 Num.PI_4 : Num
1458 ```
1460 $\frac{\pi}{4}$
1462 ## Num.SQRT1_2
1464 ```tomo
1465 Num.SQRT1_2 : Num
1466 ```
1468 $\sqrt{\frac{1}{2}}$
1470 ## Num.SQRT2
1472 ```tomo
1473 Num.SQRT2 : Num
1474 ```
1476 $\sqrt{2}$
1478 ## Num.TAU
1480 ```tomo
1481 Num.TAU : Num
1482 ```
1484 Tau ($2 \times \pi$)
1486 ## Num.abs
1488 ```tomo
1489 Num.abs : func(n: Num -> Num)
1490 ```
1492 Calculates the absolute value of a number.
1494 Argument | Type | Description | Default
1495 ---------|------|-------------|---------
1496 n | `Num` | The number whose absolute value is to be computed. | -
1498 **Return:** The absolute value of `n`.
1501 **Example:**
1502 ```tomo
1503 assert (-3.5).abs() == 3.5
1505 ```
1506 ## Num.acos
1508 ```tomo
1509 Num.acos : func(x: Num -> Num)
1510 ```
1512 Computes the arc cosine of a number.
1514 Argument | Type | Description | Default
1515 ---------|------|-------------|---------
1516 x | `Num` | The number for which the arc cosine is to be calculated. | -
1518 **Return:** The arc cosine of `x` in radians.
1521 **Example:**
1522 ```tomo
1523 assert (0.0).acos().near(1.5707963267948966)
1525 ```
1526 ## Num.acosh
1528 ```tomo
1529 Num.acosh : func(x: Num -> Num)
1530 ```
1532 Computes the inverse hyperbolic cosine of a number.
1534 Argument | Type | Description | Default
1535 ---------|------|-------------|---------
1536 x | `Num` | The number for which the inverse hyperbolic cosine is to be calculated. | -
1538 **Return:** The inverse hyperbolic cosine of `x`.
1541 **Example:**
1542 ```tomo
1543 assert (1.0).acosh() == 0
1545 ```
1546 ## Num.asin
1548 ```tomo
1549 Num.asin : func(x: Num -> Num)
1550 ```
1552 Computes the arc sine of a number.
1554 Argument | Type | Description | Default
1555 ---------|------|-------------|---------
1556 x | `Num` | The number for which the arc sine is to be calculated. | -
1558 **Return:** The arc sine of `x` in radians.
1561 **Example:**
1562 ```tomo
1563 assert (0.5).asin().near(0.5235987755982989)
1565 ```
1566 ## Num.asinh
1568 ```tomo
1569 Num.asinh : func(x: Num -> Num)
1570 ```
1572 Computes the inverse hyperbolic sine of a number.
1574 Argument | Type | Description | Default
1575 ---------|------|-------------|---------
1576 x | `Num` | The number for which the inverse hyperbolic sine is to be calculated. | -
1578 **Return:** The inverse hyperbolic sine of `x`.
1581 **Example:**
1582 ```tomo
1583 assert (0.0).asinh() == 0
1585 ```
1586 ## Num.atan
1588 ```tomo
1589 Num.atan : func(x: Num -> Num)
1590 ```
1592 Computes the arc tangent of a number.
1594 Argument | Type | Description | Default
1595 ---------|------|-------------|---------
1596 x | `Num` | The number for which the arc tangent is to be calculated. | -
1598 **Return:** The arc tangent of `x` in radians.
1601 **Example:**
1602 ```tomo
1603 assert (1.0).atan().near(0.7853981633974483)
1605 ```
1606 ## Num.atan2
1608 ```tomo
1609 Num.atan2 : func(x: Num, y: Num -> Num)
1610 ```
1612 Computes the arc tangent of the quotient of two numbers.
1614 Argument | Type | Description | Default
1615 ---------|------|-------------|---------
1616 x | `Num` | The numerator. | -
1617 y | `Num` | The denominator. | -
1619 **Return:** The arc tangent of `x/y` in radians.
1622 **Example:**
1623 ```tomo
1624 assert Num.atan2(1, 1).near(0.7853981633974483)
1626 ```
1627 ## Num.atanh
1629 ```tomo
1630 Num.atanh : func(x: Num -> Num)
1631 ```
1633 Computes the inverse hyperbolic tangent of a number.
1635 Argument | Type | Description | Default
1636 ---------|------|-------------|---------
1637 x | `Num` | The number for which the inverse hyperbolic tangent is to be calculated. | -
1639 **Return:** The inverse hyperbolic tangent of `x`.
1642 **Example:**
1643 ```tomo
1644 assert (0.5).atanh().near(0.5493061443340549)
1646 ```
1647 ## Num.cbrt
1649 ```tomo
1650 Num.cbrt : func(x: Num -> Num)
1651 ```
1653 Computes the cube root of a number.
1655 Argument | Type | Description | Default
1656 ---------|------|-------------|---------
1657 x | `Num` | The number for which the cube root is to be calculated. | -
1659 **Return:** The cube root of `x`.
1662 **Example:**
1663 ```tomo
1664 assert (27.0).cbrt() == 3
1666 ```
1667 ## Num.ceil
1669 ```tomo
1670 Num.ceil : func(x: Num -> Num)
1671 ```
1673 Rounds a number up to the nearest integer.
1675 Argument | Type | Description | Default
1676 ---------|------|-------------|---------
1677 x | `Num` | The number to be rounded up. | -
1679 **Return:** The smallest integer greater than or equal to `x`.
1682 **Example:**
1683 ```tomo
1684 assert (3.2).ceil() == 4
1686 ```
1687 ## Num.clamped
1689 ```tomo
1690 Num.clamped : func(x: Num, low: Num, high: Num -> Num)
1691 ```
1693 Returns the given number clamped between two values so that it is within that range.
1695 Argument | Type | Description | Default
1696 ---------|------|-------------|---------
1697 x | `Num` | The number to clamp. | -
1698 low | `Num` | The lowest value the result can take. | -
1699 high | `Num` | The highest value the result can take. | -
1701 **Return:** The first argument clamped between the other two arguments.
1704 **Example:**
1705 ```tomo
1706 assert (2.5).clamped(5.5, 10.5) == 5.5
1708 ```
1709 ## Num.copysign
1711 ```tomo
1712 Num.copysign : func(x: Num, y: Num -> Num)
1713 ```
1715 Copies the sign of one number to another.
1717 Argument | Type | Description | Default
1718 ---------|------|-------------|---------
1719 x | `Num` | The number whose magnitude will be copied. | -
1720 y | `Num` | The number whose sign will be copied. | -
1722 **Return:** A number with the magnitude of `x` and the sign of `y`.
1725 **Example:**
1726 ```tomo
1727 assert (3.0).copysign(-1) == -3
1729 ```
1730 ## Num.cos
1732 ```tomo
1733 Num.cos : func(x: Num -> Num)
1734 ```
1736 Computes the cosine of a number (angle in radians).
1738 Argument | Type | Description | Default
1739 ---------|------|-------------|---------
1740 x | `Num` | The angle in radians. | -
1742 **Return:** The cosine of `x`.
1745 **Example:**
1746 ```tomo
1747 assert (0.0).cos() == 1
1749 ```
1750 ## Num.cosh
1752 ```tomo
1753 Num.cosh : func(x: Num -> Num)
1754 ```
1756 Computes the hyperbolic cosine of a number.
1758 Argument | Type | Description | Default
1759 ---------|------|-------------|---------
1760 x | `Num` | The number for which the hyperbolic cosine is to be calculated. | -
1762 **Return:** The hyperbolic cosine of `x`.
1765 **Example:**
1766 ```tomo
1767 assert (0.0).cosh() == 1
1769 ```
1770 ## Num.erf
1772 ```tomo
1773 Num.erf : func(x: Num -> Num)
1774 ```
1776 Computes the error function of a number.
1778 Argument | Type | Description | Default
1779 ---------|------|-------------|---------
1780 x | `Num` | The number for which the error function is to be calculated. | -
1782 **Return:** The error function of `x`.
1785 **Example:**
1786 ```tomo
1787 assert (0.0).erf() == 0
1789 ```
1790 ## Num.erfc
1792 ```tomo
1793 Num.erfc : func(x: Num -> Num)
1794 ```
1796 Computes the complementary error function of a number.
1798 Argument | Type | Description | Default
1799 ---------|------|-------------|---------
1800 x | `Num` | The number for which the complementary error function is to be calculated. | -
1802 **Return:** The complementary error function of `x`.
1805 **Example:**
1806 ```tomo
1807 assert (0.0).erfc() == 1
1809 ```
1810 ## Num.exp
1812 ```tomo
1813 Num.exp : func(x: Num -> Num)
1814 ```
1816 Computes the exponential function $e^x$ for a number.
1818 Argument | Type | Description | Default
1819 ---------|------|-------------|---------
1820 x | `Num` | The exponent. | -
1822 **Return:** The value of $e^x$.
1825 **Example:**
1826 ```tomo
1827 assert (1.0).exp().near(2.718281828459045)
1829 ```
1830 ## Num.exp2
1832 ```tomo
1833 Num.exp2 : func(x: Num -> Num)
1834 ```
1836 Computes $2^x$ for a number.
1838 Argument | Type | Description | Default
1839 ---------|------|-------------|---------
1840 x | `Num` | The exponent. | -
1842 **Return:** The value of $2^x$.
1845 **Example:**
1846 ```tomo
1847 assert (3.0).exp2() == 8
1849 ```
1850 ## Num.expm1
1852 ```tomo
1853 Num.expm1 : func(x: Num -> Num)
1854 ```
1856 Computes $e^x - 1$ for a number.
1858 Argument | Type | Description | Default
1859 ---------|------|-------------|---------
1860 x | `Num` | The exponent. | -
1862 **Return:** The value of $e^x - 1$.
1865 **Example:**
1866 ```tomo
1867 assert (1.0).expm1().near(1.7182818284590453)
1869 ```
1870 ## Num.fdim
1872 ```tomo
1873 Num.fdim : func(x: Num, y: Num -> Num)
1874 ```
1876 Computes the positive difference between two numbers.
1878 Argument | Type | Description | Default
1879 ---------|------|-------------|---------
1880 x | `Num` | The first number. | -
1881 y | `Num` | The second number. | -
1883 **Return:** The positive difference $\max(0, x - y)$.
1886 **Example:**
1887 ```tomo
1888 assert (5.0).fdim(3) == 2
1890 ```
1891 ## Num.floor
1893 ```tomo
1894 Num.floor : func(x: Num -> Num)
1895 ```
1897 Rounds a number down to the nearest integer.
1899 Argument | Type | Description | Default
1900 ---------|------|-------------|---------
1901 x | `Num` | The number to be rounded down. | -
1903 **Return:** The largest integer less than or equal to `x`.
1906 **Example:**
1907 ```tomo
1908 assert (3.7).floor() == 3
1910 ```
1911 ## Num.hypot
1913 ```tomo
1914 Num.hypot : func(x: Num, y: Num -> Num)
1915 ```
1917 Computes the Euclidean norm, $\sqrt{x^2 + y^2}$, of two numbers.
1919 Argument | Type | Description | Default
1920 ---------|------|-------------|---------
1921 x | `Num` | The first number. | -
1922 y | `Num` | The second number. | -
1924 **Return:** The Euclidean norm of `x` and `y`.
1927 **Example:**
1928 ```tomo
1929 assert Num.hypot(3, 4) == 5
1931 ```
1932 ## Num.is_between
1934 ```tomo
1935 Num.is_between : func(x: Num, low: Num, high: Num -> Bool)
1936 ```
1938 Determines if a number is between two numbers (inclusive).
1940 Argument | Type | Description | Default
1941 ---------|------|-------------|---------
1942 x | `Num` | The integer to be checked. | -
1943 low | `Num` | One end of the range to check (inclusive). | -
1944 high | `Num` | The other end of the range to check (inclusive). | -
1946 **Return:** `yes` if `a <= x and x <= b` or `b <= x and x <= a`, otherwise `no`
1949 **Example:**
1950 ```tomo
1951 assert (7.5).is_between(1, 10) == yes
1952 assert (7.5).is_between(10, 1) == yes
1953 assert (7.5).is_between(100, 200) == no
1954 assert (7.5).is_between(1, 7.5) == yes
1956 ```
1957 ## Num.isfinite
1959 ```tomo
1960 Num.isfinite : func(n: Num -> Bool)
1961 ```
1963 Checks if a number is finite.
1965 Argument | Type | Description | Default
1966 ---------|------|-------------|---------
1967 n | `Num` | The number to be checked. | -
1969 **Return:** `yes` if `n` is finite, `no` otherwise.
1972 **Example:**
1973 ```tomo
1974 assert (1.0).isfinite() == yes
1975 assert Num.INF.isfinite() == no
1977 ```
1978 ## Num.isinf
1980 ```tomo
1981 Num.isinf : func(n: Num -> Bool)
1982 ```
1984 Checks if a number is infinite.
1986 Argument | Type | Description | Default
1987 ---------|------|-------------|---------
1988 n | `Num` | The number to be checked. | -
1990 **Return:** `yes` if `n` is infinite, `no` otherwise.
1993 **Example:**
1994 ```tomo
1995 assert Num.INF.isinf() == yes
1996 assert (1.0).isinf() == no
1998 ```
1999 ## Num.j0
2001 ```tomo
2002 Num.j0 : func(x: Num -> Num)
2003 ```
2005 Computes the Bessel function of the first kind of order 0.
2007 Argument | Type | Description | Default
2008 ---------|------|-------------|---------
2009 x | `Num` | The number for which the Bessel function is to be calculated. | -
2011 **Return:** The Bessel function of the first kind of order 0 of `x`.
2014 **Example:**
2015 ```tomo
2016 assert (0.0).j0() == 1
2018 ```
2019 ## Num.j1
2021 ```tomo
2022 Num.j1 : func(x: Num -> Num)
2023 ```
2025 Computes the Bessel function of the first kind of order 1.
2027 Argument | Type | Description | Default
2028 ---------|------|-------------|---------
2029 x | `Num` | The number for which the Bessel function is to be calculated. | -
2031 **Return:** The Bessel function of the first kind of order 1 of `x`.
2034 **Example:**
2035 ```tomo
2036 assert (0.0).j1() == 0
2038 ```
2039 ## Num.log
2041 ```tomo
2042 Num.log : func(x: Num -> Num)
2043 ```
2045 Computes the natural logarithm (base $e$) of a number.
2047 Argument | Type | Description | Default
2048 ---------|------|-------------|---------
2049 x | `Num` | The number for which the natural logarithm is to be calculated. | -
2051 **Return:** The natural logarithm of `x`.
2054 **Example:**
2055 ```tomo
2056 assert Num.E.log() == 1
2058 ```
2059 ## Num.log10
2061 ```tomo
2062 Num.log10 : func(x: Num -> Num)
2063 ```
2065 Computes the base-10 logarithm of a number.
2067 Argument | Type | Description | Default
2068 ---------|------|-------------|---------
2069 x | `Num` | The number for which the base-10 logarithm is to be calculated. | -
2071 **Return:** The base-10 logarithm of `x`.
2074 **Example:**
2075 ```tomo
2076 assert (100.0).log10() == 2
2078 ```
2079 ## Num.log1p
2081 ```tomo
2082 Num.log1p : func(x: Num -> Num)
2083 ```
2085 Computes $\log(1 + x)$ for a number.
2087 Argument | Type | Description | Default
2088 ---------|------|-------------|---------
2089 x | `Num` | The number for which $\log(1 + x)$ is to be calculated. | -
2091 **Return:** The value of $\log(1 + x)$.
2094 **Example:**
2095 ```tomo
2096 assert (1.0).log1p().near(0.6931471805599453)
2098 ```
2099 ## Num.log2
2101 ```tomo
2102 Num.log2 : func(x: Num -> Num)
2103 ```
2105 Computes the base-2 logarithm of a number.
2107 Argument | Type | Description | Default
2108 ---------|------|-------------|---------
2109 x | `Num` | The number for which the base-2 logarithm is to be calculated. | -
2111 **Return:** The base-2 logarithm of `x`.
2114 **Example:**
2115 ```tomo
2116 assert (8.0).log2() == 3
2118 ```
2119 ## Num.logb
2121 ```tomo
2122 Num.logb : func(x: Num -> Num)
2123 ```
2125 Computes the binary exponent (base-2 logarithm) of a number.
2127 Argument | Type | Description | Default
2128 ---------|------|-------------|---------
2129 x | `Num` | The number for which the binary exponent is to be calculated. | -
2131 **Return:** The binary exponent of `x`.
2134 **Example:**
2135 ```tomo
2136 assert (8.0).logb() == 3
2138 ```
2139 ## Num.mix
2141 ```tomo
2142 Num.mix : func(amount: Num, x: Num, y: Num -> Num)
2143 ```
2145 Interpolates between two numbers based on a given amount.
2147 Argument | Type | Description | Default
2148 ---------|------|-------------|---------
2149 amount | `Num` | The interpolation factor (between `0` and `1`). | -
2150 x | `Num` | The starting number. | -
2151 y | `Num` | The ending number. | -
2153 **Return:** The interpolated number between `x` and `y` based on `amount`.
2156 **Example:**
2157 ```tomo
2158 assert (0.5).mix(10, 20) == 15
2159 assert (0.25).mix(10, 20) == 12.5
2161 ```
2162 ## Num.near
2164 ```tomo
2165 Num.near : func(x: Num, y: Num, ratio: Num = 1e-9, min_epsilon: Num = 1e-9 -> Bool)
2166 ```
2168 Checks if two numbers are approximately equal within specified tolerances. If two numbers are within an absolute difference or the ratio between the two is small enough, they are considered near each other.
2170 Argument | Type | Description | Default
2171 ---------|------|-------------|---------
2172 x | `Num` | The first number. | -
2173 y | `Num` | The second number. | -
2174 ratio | `Num` | The relative tolerance. Default is `1e-9`. | `1e-9`
2175 min_epsilon | `Num` | The absolute tolerance. Default is `1e-9`. | `1e-9`
2177 **Return:** `yes` if `x` and `y` are approximately equal within the specified tolerances, `no` otherwise.
2180 **Example:**
2181 ```tomo
2182 assert (1.0).near(1.000000001) == yes
2183 assert (100.0).near(110, ratio=0.1) == yes
2184 assert (5.0).near(5.1, min_epsilon=0.1) == yes
2186 ```
2187 ## Num.nextafter
2189 ```tomo
2190 Num.nextafter : func(x: Num, y: Num -> Num)
2191 ```
2193 Computes the next representable value after a given number towards a specified direction.
2195 Argument | Type | Description | Default
2196 ---------|------|-------------|---------
2197 x | `Num` | The starting number. | -
2198 y | `Num` | The direction towards which to find the next representable value. | -
2200 **Return:** The next representable value after `x` in the direction of `y`.
2203 **Example:**
2204 ```tomo
2205 assert (1.0).nextafter(1.1) == 1.0000000000000002
2207 ```
2208 ## Num.parse
2210 ```tomo
2211 Num.parse : func(text: Text, remainder: &Text? = none -> Num?)
2212 ```
2214 Converts a text representation of a number into a floating-point number.
2216 Argument | Type | Description | Default
2217 ---------|------|-------------|---------
2218 text | `Text` | The text containing the number. | -
2219 remainder | `&Text?` | If non-none, this argument will be set to the remainder of the text after the matching part. If none, parsing will only succeed if the entire text matches. | `none`
2221 **Return:** The number represented by the text or `none` if the entire text can't be parsed as a number.
2224 **Example:**
2225 ```tomo
2226 assert Num.parse("3.14") == 3.14
2227 assert Num.parse("1e3") == 1000
2228 assert Num.parse("1.5junk") == none
2229 remainder : Text
2230 assert Num.parse("1.5junk", &remainder) == 1.5
2231 assert remainder == "junk"
2233 ```
2234 ## Num.percent
2236 ```tomo
2237 Num.percent : func(n: Num, precision: Num = 0.01 -> Text)
2238 ```
2240 Convert a number into a percentage text with a percent sign.
2242 Argument | Type | Description | Default
2243 ---------|------|-------------|---------
2244 n | `Num` | The number to be converted to a percent. | -
2245 precision | `Num` | Round the percentage to this precision level. | `0.01`
2247 **Return:** A text representation of the number as a percentage with a percent sign.
2250 **Example:**
2251 ```tomo
2252 assert (0.5).percent() == "50%"
2253 assert (1./3.).percent(2) == "34%"
2254 assert (1./3.).percent(precision=0.0001) == "33.3333%"
2255 assert (1./3.).percent(precision=10.) == "30%"
2257 ```
2258 ## Num.rint
2260 ```tomo
2261 Num.rint : func(x: Num -> Num)
2262 ```
2264 Rounds a number to the nearest integer, with ties rounded to the nearest even integer.
2266 Argument | Type | Description | Default
2267 ---------|------|-------------|---------
2268 x | `Num` | The number to be rounded. | -
2270 **Return:** The nearest integer value of `x`.
2273 **Example:**
2274 ```tomo
2275 assert (3.5).rint() == 4
2276 assert (2.5).rint() == 2
2278 ```
2279 ## Num.round
2281 ```tomo
2282 Num.round : func(x: Num -> Num)
2283 ```
2285 Rounds a number to the nearest whole number integer.
2287 Argument | Type | Description | Default
2288 ---------|------|-------------|---------
2289 x | `Num` | The number to be rounded. | -
2291 **Return:** The nearest integer value of `x`.
2294 **Example:**
2295 ```tomo
2296 assert (2.3).round() == 2
2297 assert (2.7).round() == 3
2299 ```
2300 ## Num.significand
2302 ```tomo
2303 Num.significand : func(x: Num -> Num)
2304 ```
2306 Extracts the significand (or mantissa) of a number.
2308 Argument | Type | Description | Default
2309 ---------|------|-------------|---------
2310 x | `Num` | The number from which to extract the significand. | -
2312 **Return:** The significand of `x`.
2315 **Example:**
2316 ```tomo
2317 assert (1234.567).significand() == 1.2056318359375
2319 ```
2320 ## Num.sin
2322 ```tomo
2323 Num.sin : func(x: Num -> Num)
2324 ```
2326 Computes the sine of a number (angle in radians).
2328 Argument | Type | Description | Default
2329 ---------|------|-------------|---------
2330 x | `Num` | The angle in radians. | -
2332 **Return:** The sine of `x`.
2335 **Example:**
2336 ```tomo
2337 assert (0.0).sin() == 0
2339 ```
2340 ## Num.sinh
2342 ```tomo
2343 Num.sinh : func(x: Num -> Num)
2344 ```
2346 Computes the hyperbolic sine of a number.
2348 Argument | Type | Description | Default
2349 ---------|------|-------------|---------
2350 x | `Num` | The number for which the hyperbolic sine is to be calculated. | -
2352 **Return:** The hyperbolic sine of `x`.
2355 **Example:**
2356 ```tomo
2357 assert (0.0).sinh() == 0
2359 ```
2360 ## Num.sqrt
2362 ```tomo
2363 Num.sqrt : func(x: Num -> Num)
2364 ```
2366 Computes the square root of a number.
2368 Argument | Type | Description | Default
2369 ---------|------|-------------|---------
2370 x | `Num` | The number for which the square root is to be calculated. | -
2372 **Return:** The square root of `x`.
2375 **Example:**
2376 ```tomo
2377 assert (16.0).sqrt() == 4
2379 ```
2380 ## Num.tan
2382 ```tomo
2383 Num.tan : func(x: Num -> Num)
2384 ```
2386 Computes the tangent of a number (angle in radians).
2388 Argument | Type | Description | Default
2389 ---------|------|-------------|---------
2390 x | `Num` | The angle in radians. | -
2392 **Return:** The tangent of `x`.
2395 **Example:**
2396 ```tomo
2397 assert (0.0).tan() == 0
2399 ```
2400 ## Num.tanh
2402 ```tomo
2403 Num.tanh : func(x: Num -> Num)
2404 ```
2406 Computes the hyperbolic tangent of a number.
2408 Argument | Type | Description | Default
2409 ---------|------|-------------|---------
2410 x | `Num` | The number for which the hyperbolic tangent is to be calculated. | -
2412 **Return:** The hyperbolic tangent of `x`.
2415 **Example:**
2416 ```tomo
2417 assert (0.0).tanh() == 0
2419 ```
2420 ## Num.tgamma
2422 ```tomo
2423 Num.tgamma : func(x: Num -> Num)
2424 ```
2426 Computes the gamma function of a number.
2428 Argument | Type | Description | Default
2429 ---------|------|-------------|---------
2430 x | `Num` | The number for which the gamma function is to be calculated. | -
2432 **Return:** The gamma function of `x`.
2435 **Example:**
2436 ```tomo
2437 assert (1.0).tgamma() == 1
2439 ```
2440 ## Num.trunc
2442 ```tomo
2443 Num.trunc : func(x: Num -> Num)
2444 ```
2446 Truncates a number to the nearest integer towards zero.
2448 Argument | Type | Description | Default
2449 ---------|------|-------------|---------
2450 x | `Num` | The number to be truncated. | -
2452 **Return:** The integer part of `x` towards zero.
2455 **Example:**
2456 ```tomo
2457 assert (3.7).trunc() == 3
2458 assert (-3.7).trunc() == -3
2460 ```
2461 ## Num.with_precision
2463 ```tomo
2464 Num.with_precision : func(n: Num, precision: Num -> Num)
2465 ```
2467 Round a number to the given precision level (specified as `10`, `.1`, `.001` etc).
2469 Argument | Type | Description | Default
2470 ---------|------|-------------|---------
2471 n | `Num` | The number to be rounded to a given precision. | -
2472 precision | `Num` | The precision to which the number should be rounded. | -
2474 **Return:** The number, rounded to the given precision level.
2477 **Example:**
2478 ```tomo
2479 assert (0.1234567).with_precision(0.01) == 0.12
2480 assert (123456.).with_precision(100) == 123500
2481 assert (1234567.).with_precision(5) == 1234565
2483 ```
2484 ## Num.y0
2486 ```tomo
2487 Num.y0 : func(x: Num -> Num)
2488 ```
2490 Computes the Bessel function of the second kind of order 0.
2492 Argument | Type | Description | Default
2493 ---------|------|-------------|---------
2494 x | `Num` | The number for which the Bessel function is to be calculated. | -
2496 **Return:** The Bessel function of the second kind of order 0 of `x`.
2499 **Example:**
2500 ```tomo
2501 assert (1.0).y0().near(0.08825696421567698)
2503 ```
2504 ## Num.y1
2506 ```tomo
2507 Num.y1 : func(x: Num -> Num)
2508 ```
2510 Computes the Bessel function of the second kind of order 1.
2512 Argument | Type | Description | Default
2513 ---------|------|-------------|---------
2514 x | `Num` | The number for which the Bessel function is to be calculated. | -
2516 **Return:** The Bessel function of the second kind of order 1 of `x`.
2519 **Example:**
2520 ```tomo
2521 assert (1.0).y1().near(-0.7812128213002887)
2523 ```
2525 # Path
2526 ## Path.accessed
2528 ```tomo
2529 Path.accessed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)
2530 ```
2532 Gets the file access time of a file.
2534 Argument | Type | Description | Default
2535 ---------|------|-------------|---------
2536 path | `Path` | The path of the file whose access time you want. | -
2537 follow_symlinks | `Bool` | Whether to follow symbolic links. | `yes`
2539 **Return:** A 64-bit unix epoch timestamp representing when the file or directory was last accessed, or `none` if no such file or directory exists.
2542 **Example:**
2543 ```tomo
2544 assert (./file.txt).accessed() == Int64(1704221100)
2545 assert (./not-a-file).accessed() == none
2547 ```
2548 ## Path.append
2550 ```tomo
2551 Path.append : func(path: Path, text: Text, permissions: Int32 = Int32(0o644) -> Result)
2552 ```
2554 Appends the given text to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.
2556 Argument | Type | Description | Default
2557 ---------|------|-------------|---------
2558 path | `Path` | The path of the file to append to. | -
2559 text | `Text` | The text to append to the file. | -
2560 permissions | `Int32` | The permissions to set on the file if it is being created. | `Int32(0o644)`
2562 **Return:** Either `Success` or `Failure(reason)`.
2565 **Example:**
2566 ```tomo
2567 (./log.txt).append("extra line\n")!
2569 ```
2570 ## Path.append_bytes
2572 ```tomo
2573 Path.append_bytes : func(path: Path, bytes: [Byte], permissions: Int32 = Int32(0o644) -> Result)
2574 ```
2576 Appends the given bytes to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.
2578 Argument | Type | Description | Default
2579 ---------|------|-------------|---------
2580 path | `Path` | The path of the file to append to. | -
2581 bytes | `[Byte]` | The bytes to append to the file. | -
2582 permissions | `Int32` | The permissions to set on the file if it is being created. | `Int32(0o644)`
2584 **Return:** Either `Success` or `Failure(reason)`.
2587 **Example:**
2588 ```tomo
2589 (./log.txt).append_bytes([104, 105])!
2591 ```
2592 ## Path.base_name
2594 ```tomo
2595 Path.base_name : func(path: Path -> Text)
2596 ```
2598 Returns the base name of the file or directory at the specified path.
2600 Argument | Type | Description | Default
2601 ---------|------|-------------|---------
2602 path | `Path` | The path of the file or directory. | -
2604 **Return:** The base name of the file or directory.
2607 **Example:**
2608 ```tomo
2609 assert (./path/to/file.txt).base_name() == "file.txt"
2611 ```
2612 ## Path.by_line
2614 ```tomo
2615 Path.by_line : func(path: Path -> func(->Text?)?)
2616 ```
2618 Returns an iterator that can be used to iterate over a file one line at a time, or returns none if the file could not be opened.
2620 Argument | Type | Description | Default
2621 ---------|------|-------------|---------
2622 path | `Path` | The path of the file. | -
2624 **Return:** An iterator that can be used to get lines from a file one at a time or none if the file couldn't be read.
2627 **Example:**
2628 ```tomo
2629 # Safely handle file not being readable:
2630 if lines := (./file.txt).by_line()
2631 for line in lines
2632 say(line.upper())
2633 else
2634 say("Couldn't read file!")
2636 # Assume the file is readable and error if that's not the case:
2637 for line in (/dev/stdin).by_line()!
2638 say(line.upper())
2640 ```
2641 ## Path.byte_writer
2643 ```tomo
2644 Path.byte_writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(bytes:[Byte], close:Bool=no -> Result))
2645 ```
2647 Returns a function that can be used to repeatedly write bytes to the same file.
2649 The file writer will keep its file descriptor open after each write (unless the `close` argument is set to `yes`). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.
2651 Argument | Type | Description | Default
2652 ---------|------|-------------|---------
2653 path | `Path` | The path of the file to write to. | -
2654 append | `Bool` | If set to `yes`, writes to the file will append. If set to `no`, then the first write to the file will overwrite its contents and subsequent calls will append. | `no`
2655 permissions | `Int32` | The permissions to set on the file if it is created. | `Int32(0o644)`
2657 **Return:** Returns a function that can repeatedly write bytes to the same file. If `close` is set to `yes`, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.
2660 **Example:**
2661 ```tomo
2662 write := (./file.txt).byte_writer()
2663 write("Hello\n".utf8())!
2664 write("world\n".utf8(), close=yes)!
2666 ```
2667 ## Path.can_execute
2669 ```tomo
2670 Path.can_execute : func(path: Path -> Bool)
2671 ```
2673 Returns whether or not a file can be executed by the current user/group.
2675 Argument | Type | Description | Default
2676 ---------|------|-------------|---------
2677 path | `Path` | The path of the file to check. | -
2679 **Return:** `yes` if the file or directory exists and the current user has execute permissions, otherwise `no`.
2682 **Example:**
2683 ```tomo
2684 assert (/bin/sh).can_execute() == yes
2685 assert (/usr/include/stdlib.h).can_execute() == no
2686 assert (/non/existant/file).can_execute() == no
2688 ```
2689 ## Path.can_read
2691 ```tomo
2692 Path.can_read : func(path: Path -> Bool)
2693 ```
2695 Returns whether or not a file can be read by the current user/group.
2697 Argument | Type | Description | Default
2698 ---------|------|-------------|---------
2699 path | `Path` | The path of the file to check. | -
2701 **Return:** `yes` if the file or directory exists and the current user has read permissions, otherwise `no`.
2704 **Example:**
2705 ```tomo
2706 assert (/usr/include/stdlib.h).can_read() == yes
2707 assert (/etc/shadow).can_read() == no
2708 assert (/non/existant/file).can_read() == no
2710 ```
2711 ## Path.can_write
2713 ```tomo
2714 Path.can_write : func(path: Path -> Bool)
2715 ```
2717 Returns whether or not a file can be written by the current user/group.
2719 Argument | Type | Description | Default
2720 ---------|------|-------------|---------
2721 path | `Path` | The path of the file to check. | -
2723 **Return:** `yes` if the file or directory exists and the current user has write permissions, otherwise `no`.
2726 **Example:**
2727 ```tomo
2728 assert (/tmp).can_write() == yes
2729 assert (/etc/passwd).can_write() == no
2730 assert (/non/existant/file).can_write() == no
2732 ```
2733 ## Path.changed
2735 ```tomo
2736 Path.changed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)
2737 ```
2739 Gets the file change time of a file.
2741 This is the ["ctime"](https://en.wikipedia.org/wiki/Stat_(system_call)#ctime) of a file, which is _not_ the file creation time.
2743 Argument | Type | Description | Default
2744 ---------|------|-------------|---------
2745 path | `Path` | The path of the file whose change time you want. | -
2746 follow_symlinks | `Bool` | Whether to follow symbolic links. | `yes`
2748 **Return:** A 64-bit unix epoch timestamp representing when the file or directory was last changed, or `none` if no such file or directory exists.
2751 **Example:**
2752 ```tomo
2753 assert (./file.txt).changed() == Int64(1704221100)
2754 assert (./not-a-file).changed() == none
2756 ```
2757 ## Path.child
2759 ```tomo
2760 Path.child : func(path: Path, child: Text -> Path)
2761 ```
2763 Return a path that is a child of another path.
2765 Argument | Type | Description | Default
2766 ---------|------|-------------|---------
2767 path | `Path` | The path of a directory. | -
2768 child | `Text` | The name of a child file or directory. | -
2770 **Return:** A new path representing the child.
2773 **Example:**
2774 ```tomo
2775 assert (./directory).child("file.txt") == (./directory/file.txt)
2777 ```
2778 ## Path.children
2780 ```tomo
2781 Path.children : func(path: Path, include_hidden = no -> [Path])
2782 ```
2784 Returns a list of children (files and directories) within the directory at the specified path. Optionally includes hidden files. Child ordering is not specified.
2786 Argument | Type | Description | Default
2787 ---------|------|-------------|---------
2788 path | `Path` | The path of the directory. | -
2789 include_hidden | `` | Whether to include hidden files (those starting with a `.`). | `no`
2791 **Return:** A list of paths for the children.
2794 **Example:**
2795 ```tomo
2796 assert (./directory).children(include_hidden=yes) == [(./directory/.git), (./directory/foo.txt)]
2798 ```
2799 ## Path.create_directory
2801 ```tomo
2802 Path.create_directory : func(path: Path, permissions = Int32(0o755), recursive = yes -> Result)
2803 ```
2805 Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.
2808 Argument | Type | Description | Default
2809 ---------|------|-------------|---------
2810 path | `Path` | The path of the directory to create. | -
2811 permissions | `` | The permissions to set on the new directory. | `Int32(0o755)`
2812 recursive | `` | If set to `yes`, then recursively create any parent directories if they don't exist, otherwise fail if the parent directory does not exist. When set to `yes`, this function behaves like `mkdir -p`. | `yes`
2814 **Return:** Either `Success` or `Failure(reason)`.
2817 **Example:**
2818 ```tomo
2819 (./new_directory).create_directory()!
2821 ```
2822 ## Path.current_dir
2824 ```tomo
2825 Path.current_dir : func(-> Path)
2826 ```
2828 Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.
2831 **Return:** The absolute path of the current directory.
2834 **Example:**
2835 ```tomo
2836 assert Path.current_dir() == (/home/user/tomo)
2838 ```
2839 ## Path.each_child
2841 ```tomo
2842 Path.each_child : func(path: Path, include_hidden = no -> func(->Path?)?)
2843 ```
2845 Returns an iterator over the children (files and directories) within the directory at the specified path. Optionally includes hidden files. Iteration order is not specified.
2847 Argument | Type | Description | Default
2848 ---------|------|-------------|---------
2849 path | `Path` | The path of the directory. | -
2850 include_hidden | `` | Whether to include hidden files (those starting with a `.`). | `no`
2852 **Return:** An iterator over the children in a directory or `none` if the path is not a directory or a symlink to a directory.
2855 **Example:**
2856 ```tomo
2857 for child in (/dir).each_child()
2858 say("Child: $child")
2860 ```
2861 ## Path.exists
2863 ```tomo
2864 Path.exists : func(path: Path -> Bool)
2865 ```
2867 Checks if a file or directory exists at the specified path.
2869 Argument | Type | Description | Default
2870 ---------|------|-------------|---------
2871 path | `Path` | The path to check. | -
2873 **Return:** `True` if the file or directory exists, `False` otherwise.
2876 **Example:**
2877 ```tomo
2878 assert (/).exists() == yes
2880 ```
2881 ## Path.expand_home
2883 ```tomo
2884 Path.expand_home : func(path: Path -> Path)
2885 ```
2887 For home-based paths (those starting with `~`), expand the path to replace the tilde with and absolute path to the user's `$HOME` directory.
2889 Argument | Type | Description | Default
2890 ---------|------|-------------|---------
2891 path | `Path` | The path to expand. | -
2893 **Return:** If the path does not start with a `~`, then return it unmodified. Otherwise, replace the `~` with an absolute path to the user's home directory.
2896 **Example:**
2897 ```tomo
2898 # Assume current user is 'user'
2899 assert (~/foo).expand_home() == (/home/user/foo)
2900 # No change
2901 assert (/foo).expand_home() == (/foo)
2903 ```
2904 ## Path.extension
2906 ```tomo
2907 Path.extension : func(path: Path, full: Bool = yes -> Text)
2908 ```
2910 Returns the file extension of the file at the specified path. Optionally returns the full extension.
2912 Argument | Type | Description | Default
2913 ---------|------|-------------|---------
2914 path | `Path` | The path of the file. | -
2915 full | `Bool` | Whether to return everything after the first `.` in the base name, or only the last part of the extension. | `yes`
2917 **Return:** The file extension (not including the leading `.`) or an empty text if there is no file extension.
2920 **Example:**
2921 ```tomo
2922 assert (./file.tar.gz).extension() == "tar.gz"
2923 assert (./file.tar.gz).extension(full=no) == "gz"
2924 assert (/foo).extension() == ""
2925 assert (./.git).extension() == ""
2927 ```
2928 ## Path.files
2930 ```tomo
2931 Path.files : func(path: Path, include_hidden: Bool = no -> [Path])
2932 ```
2934 Returns a list of files within the directory at the specified path. Optionally includes hidden files.
2936 Argument | Type | Description | Default
2937 ---------|------|-------------|---------
2938 path | `Path` | The path of the directory. | -
2939 include_hidden | `Bool` | Whether to include hidden files (those starting with a `.`). | `no`
2941 **Return:** A list of file paths.
2944 **Example:**
2945 ```tomo
2946 assert (./directory).files(include_hidden=yes) == [(./directory/file1.txt), (./directory/file2.txt)]
2948 ```
2949 ## Path.glob
2951 ```tomo
2952 Path.glob : func(path: Path -> [Path])
2953 ```
2955 Perform a globbing operation and return a list of matching paths. Some glob specific details:
2956 - The paths "." and ".." are *not* included in any globbing results.
2957 - Files or directories that begin with "." will not match `*`, but will match `.*`.
2958 - Globs do support `{a,b}` syntax for matching files that match any of several
2959 choices of patterns.
2961 - The shell-style syntax `**` for matching subdirectories is not supported.
2963 Argument | Type | Description | Default
2964 ---------|------|-------------|---------
2965 path | `Path` | The path of the directory which may contain special globbing characters like `*`, `?`, or `{...}` | -
2967 **Return:** A list of file paths that match the glob.
2970 **Example:**
2971 ```tomo
2972 # Current directory includes: foo.txt, baz.txt, qux.jpg, .hidden
2973 assert (./*).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]
2974 assert (./*.txt).glob() == [(./foo.txt), (./baz.txt)]
2975 assert (./*.{txt,jpg}).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]
2976 assert (./.*).glob() == [(./.hidden)]
2978 # Globs with no matches return an empty list:
2979 assert (./*.xxx).glob() == []
2981 ```
2982 ## Path.group
2984 ```tomo
2985 Path.group : func(path: Path, follow_symlinks: Bool = yes -> Text?)
2986 ```
2988 Get the owning group of a file or directory.
2990 Argument | Type | Description | Default
2991 ---------|------|-------------|---------
2992 path | `Path` | The path whose owning group to get. | -
2993 follow_symlinks | `Bool` | Whether to follow symbolic links. | `yes`
2995 **Return:** The name of the group which owns the file or directory, or `none` if the path does not exist.
2998 **Example:**
2999 ```tomo
3000 assert (/bin).group() == "root"
3001 assert (/non/existent/file).group() == none
3003 ```
3004 ## Path.has_extension
3006 ```tomo
3007 Path.has_extension : func(path: Path, extension: Text -> Bool)
3008 ```
3010 Return whether or not a path has a given file extension.
3012 Argument | Type | Description | Default
3013 ---------|------|-------------|---------
3014 path | `Path` | A path. | -
3015 extension | `Text` | A file extension (leading `.` is optional). If empty, the check will test if the file does not have any file extension. | -
3017 **Return:** Whether or not the path has the given extension.
3020 **Example:**
3021 ```tomo
3022 assert (/foo.txt).has_extension("txt") == yes
3023 assert (/foo.txt).has_extension(".txt") == yes
3024 assert (/foo.tar.gz).has_extension("gz") == yes
3025 assert (/foo.tar.gz).has_extension("zip") == no
3027 ```
3028 ## Path.is_directory
3030 ```tomo
3031 Path.is_directory : func(path: Path, follow_symlinks = yes -> Bool)
3032 ```
3034 Checks if the path represents a directory. Optionally follows symbolic links.
3036 Argument | Type | Description | Default
3037 ---------|------|-------------|---------
3038 path | `Path` | The path to check. | -
3039 follow_symlinks | `` | Whether to follow symbolic links. | `yes`
3041 **Return:** `True` if the path is a directory, `False` otherwise.
3044 **Example:**
3045 ```tomo
3046 assert (./directory/).is_directory() == yes
3047 assert (./file.txt).is_directory() == no
3049 ```
3050 ## Path.is_file
3052 ```tomo
3053 Path.is_file : func(path: Path, follow_symlinks = yes -> Bool)
3054 ```
3056 Checks if the path represents a file. Optionally follows symbolic links.
3058 Argument | Type | Description | Default
3059 ---------|------|-------------|---------
3060 path | `Path` | The path to check. | -
3061 follow_symlinks | `` | Whether to follow symbolic links. | `yes`
3063 **Return:** `True` if the path is a file, `False` otherwise.
3066 **Example:**
3067 ```tomo
3068 assert (./file.txt).is_file() == yes
3069 assert (./directory/).is_file() == no
3071 ```
3072 ## Path.is_socket
3074 ```tomo
3075 Path.is_socket : func(path: Path, follow_symlinks = yes -> Bool)
3076 ```
3078 Checks if the path represents a socket. Optionally follows symbolic links.
3080 Argument | Type | Description | Default
3081 ---------|------|-------------|---------
3082 path | `Path` | The path to check. | -
3083 follow_symlinks | `` | Whether to follow symbolic links. | `yes`
3085 **Return:** `True` if the path is a socket, `False` otherwise.
3088 **Example:**
3089 ```tomo
3090 assert (./socket).is_socket() == yes
3092 ```
3093 ## Path.is_symlink
3095 ```tomo
3096 Path.is_symlink : func(path: Path -> Bool)
3097 ```
3099 Checks if the path represents a symbolic link.
3101 Argument | Type | Description | Default
3102 ---------|------|-------------|---------
3103 path | `Path` | The path to check. | -
3105 **Return:** `True` if the path is a symbolic link, `False` otherwise.
3108 **Example:**
3109 ```tomo
3110 assert (./link).is_symlink() == yes
3112 ```
3113 ## Path.lines
3115 ```tomo
3116 Path.lines : func(path: Path -> [Text]?)
3117 ```
3119 Returns a list with the lines of text in a file or returns none if the file could not be opened.
3121 Argument | Type | Description | Default
3122 ---------|------|-------------|---------
3123 path | `Path` | The path of the file. | -
3125 **Return:** A list of the lines in a file or none if the file couldn't be read.
3128 **Example:**
3129 ```tomo
3130 lines := (./file.txt).lines()!
3132 ```
3133 ## Path.matches_glob
3135 ```tomo
3136 Path.matches_glob : func(path: Path, glob: Text -> Bool)
3137 ```
3139 Return whether or not a path matches a given glob.
3141 Argument | Type | Description | Default
3142 ---------|------|-------------|---------
3143 path | `Path` | The path to check. | -
3144 glob | `Text` | The glob pattern to check. | -
3146 **Return:** Whether or not the path matches the given glob.
3149 **Example:**
3150 ```tomo
3151 assert (./file.txt).matches_glob("*.txt")
3152 assert (./file.c).matches_glob("*.{c,h}")
3154 ```
3155 ## Path.modified
3157 ```tomo
3158 Path.modified : func(path: Path, follow_symlinks: Bool = yes -> Int64?)
3159 ```
3161 Gets the file modification time of a file.
3163 Argument | Type | Description | Default
3164 ---------|------|-------------|---------
3165 path | `Path` | The path of the file whose modification time you want. | -
3166 follow_symlinks | `Bool` | Whether to follow symbolic links. | `yes`
3168 **Return:** A 64-bit unix epoch timestamp representing when the file or directory was last modified, or `none` if no such file or directory exists.
3171 **Example:**
3172 ```tomo
3173 assert (./file.txt).modified() == Int64(1704221100)
3174 assert (./not-a-file).modified() == none
3176 ```
3177 ## Path.move
3179 ```tomo
3180 Path.move : func(path: Path, dest: Path, allow_overwriting = no -> Result)
3181 ```
3183 Moves the file or directory from one location to another.
3185 Argument | Type | Description | Default
3186 ---------|------|-------------|---------
3187 path | `Path` | The path to move. | -
3188 dest | `Path` | The destination to move the path to. | -
3189 allow_overwriting | `` | Whether to permit overwriting the destination if it is an existing file or directory. | `no`
3191 **Return:** Either `Success` or `Failure(reason)`.
3194 **Example:**
3195 ```tomo
3196 (./file.txt).move(/tmp/renamed.txt)!
3198 ```
3199 ## Path.owner
3201 ```tomo
3202 Path.owner : func(path: Path, follow_symlinks: Bool = yes -> Text?)
3203 ```
3205 Get the owning user of a file or directory.
3207 Argument | Type | Description | Default
3208 ---------|------|-------------|---------
3209 path | `Path` | The path whose owner to get. | -
3210 follow_symlinks | `Bool` | Whether to follow symbolic links. | `yes`
3212 **Return:** The name of the user who owns the file or directory, or `none` if the path does not exist.
3215 **Example:**
3216 ```tomo
3217 assert (/bin).owner() == "root"
3218 assert (/non/existent/file).owner() == none
3220 ```
3221 ## Path.parent
3223 ```tomo
3224 Path.parent : func(path: Path -> Path?)
3225 ```
3227 Returns the parent directory of the file or directory at the specified path.
3229 Argument | Type | Description | Default
3230 ---------|------|-------------|---------
3231 path | `Path` | The path of the file or directory. | -
3233 **Return:** The path of the parent directory or `none` if the path is `(/)` (the file root).
3236 **Example:**
3237 ```tomo
3238 assert (./path/to/file.txt).parent() == (./path/to/)
3240 ```
3241 ## Path.read
3243 ```tomo
3244 Path.read : func(path: Path -> Text?)
3245 ```
3247 Reads the contents of the file at the specified path or none if the file could not be read.
3249 Argument | Type | Description | Default
3250 ---------|------|-------------|---------
3251 path | `Path` | The path of the file to read. | -
3253 **Return:** The contents of the file. If the file could not be read, none will be returned. If the file can be read, but is not valid UTF8 data, an error will be raised.
3256 **Example:**
3257 ```tomo
3258 assert (./hello.txt).read() == "Hello"
3259 assert (./nosuchfile.xxx).read() == none
3261 ```
3262 ## Path.read_bytes
3264 ```tomo
3265 Path.read_bytes : func(path: Path, limit: Int? = none -> [Byte]?)
3266 ```
3268 Reads the contents of the file at the specified path or none if the file could not be read.
3270 Argument | Type | Description | Default
3271 ---------|------|-------------|---------
3272 path | `Path` | The path of the file to read. | -
3273 limit | `Int?` | A limit to how many bytes should be read. | `none`
3275 **Return:** The byte contents of the file. If the file cannot be read, none will be returned.
3278 **Example:**
3279 ```tomo
3280 assert (./hello.txt).read_bytes()! == [72, 101, 108, 108, 111]
3281 assert (./nosuchfile.xxx).read_bytes() == none
3283 ```
3284 ## Path.relative_to
3286 ```tomo
3287 Path.relative_to : func(path: Path, relative_to = (./) -> Path)
3288 ```
3290 Returns the path relative to a given base path. By default, the base path is the current directory.
3292 Argument | Type | Description | Default
3293 ---------|------|-------------|---------
3294 path | `Path` | The path to convert. | -
3295 relative_to | `` | The base path for the relative path. | `(./)`
3297 **Return:** A relative path from the reference point to the given path.
3300 **Example:**
3301 ```tomo
3302 assert (./path/to/file.txt).relative_to((./path)) == (./to/file.txt)
3303 assert (/tmp/foo).relative_to((/tmp)) == (./foo)
3305 ```
3306 ## Path.remove
3308 ```tomo
3309 Path.remove : func(path: Path, ignore_missing = no -> Result)
3310 ```
3312 Removes the file or directory at the specified path. A runtime error is raised if something goes wrong.
3314 Argument | Type | Description | Default
3315 ---------|------|-------------|---------
3316 path | `Path` | The path to remove. | -
3317 ignore_missing | `` | Whether to ignore errors if the file or directory does not exist. | `no`
3319 **Return:** Either `Success` or `Failure(reason)`.
3322 **Example:**
3323 ```tomo
3324 (./file.txt).remove()!
3326 ```
3327 ## Path.resolved
3329 ```tomo
3330 Path.resolved : func(path: Path, relative_to = (./) -> Path)
3331 ```
3333 Resolves the absolute path of the given path relative to a base path. By default, the base path is the current directory.
3335 Argument | Type | Description | Default
3336 ---------|------|-------------|---------
3337 path | `Path` | The path to resolve. | -
3338 relative_to | `` | The base path for resolution. | `(./)`
3340 **Return:** The resolved absolute path.
3343 **Example:**
3344 ```tomo
3345 assert (~/foo).resolved() == (/home/user/foo)
3346 assert (./path/to/file.txt).resolved(relative_to=(/foo)) == (/foo/path/to/file.txt)
3348 ```
3349 ## Path.set_owner
3351 ```tomo
3352 Path.set_owner : func(path: Path, owner: Text? = none, group: Text? = none, follow_symlinks: Bool = yes -> Result)
3353 ```
3355 Set the owning user and/or group for a path.
3357 Argument | Type | Description | Default
3358 ---------|------|-------------|---------
3359 path | `Path` | The path to change the permissions for. | -
3360 owner | `Text?` | If non-none, the new user to assign to be the owner of the file. | `none`
3361 group | `Text?` | If non-none, the new group to assign to be the owner of the file. | `none`
3362 follow_symlinks | `Bool` | Whether to follow symbolic links. | `yes`
3364 **Return:** Either `Success` or `Failure(reason)`.
3367 **Example:**
3368 ```tomo
3369 (./file.txt).set_owner(owner="root", group="wheel")!
3371 ```
3372 ## Path.sibling
3374 ```tomo
3375 Path.sibling : func(path: Path, name: Text -> Path)
3376 ```
3378 Return a path that is a sibling of another path (i.e. has the same parent, but a different name). This is equivalent to `.parent().child(name)`
3380 Argument | Type | Description | Default
3381 ---------|------|-------------|---------
3382 path | `Path` | A path. | -
3383 name | `Text` | The name of a sibling file or directory. | -
3385 **Return:** A new path representing the sibling.
3388 **Example:**
3389 ```tomo
3390 assert (/foo/baz).sibling("doop") == (/foo/doop)
3392 ```
3393 ## Path.subdirectories
3395 ```tomo
3396 Path.subdirectories : func(path: Path, include_hidden = no -> [Path])
3397 ```
3399 Returns a list of subdirectories within the directory at the specified path. Optionally includes hidden subdirectories.
3401 Argument | Type | Description | Default
3402 ---------|------|-------------|---------
3403 path | `Path` | The path of the directory. | -
3404 include_hidden | `` | Whether to include hidden subdirectories (those starting with a `.`) | `no`
3406 **Return:** A list of subdirectory paths.
3409 **Example:**
3410 ```tomo
3411 assert (./directory).subdirectories() == [(./directory/subdir1), (./directory/subdir2)]
3412 assert (./directory).subdirectories(include_hidden=yes) == [(./directory/.git), (./directory/subdir1), (./directory/subdir2)]
3414 ```
3415 ## Path.unique_directory
3417 ```tomo
3418 Path.unique_directory : func(path: Path -> Path)
3419 ```
3421 Generates a unique directory path based on the given path. Useful for creating temporary directories.
3423 Argument | Type | Description | Default
3424 ---------|------|-------------|---------
3425 path | `Path` | The base path for generating the unique directory. The last six letters of this path must be `XXXXXX`. | -
3427 **Return:** A unique directory path after creating the directory.
3430 **Example:**
3431 ```tomo
3432 created := (/tmp/my-dir.XXXXXX).unique_directory()
3433 assert created.is_directory() == yes
3434 created.remove()!
3436 ```
3437 ## Path.walk
3439 ```tomo
3440 Path.walk : func(path: Path, include_hidden = no, follow_symlinks: Bool = no -> func(->Path?))
3441 ```
3443 Returns an iterator that efficiently recursively walks over every file and subdirectory in a given directory. The iteration order is not defined, but in practice it may look a lot like a breadth-first traversal.
3445 The path itself is always included in the iteration.
3447 Argument | Type | Description | Default
3448 ---------|------|-------------|---------
3449 path | `Path` | The path to begin the walk. | -
3450 include_hidden | `` | Whether to include hidden files (those starting with a `.`) | `no`
3451 follow_symlinks | `Bool` | Whether to follow symbolic links. Caution: if set to 'yes', it is possible for this iterator to get stuck in a loop, using increasingly large amounts of memory. | `no`
3453 **Return:** An iterator that recursively walks over every file and subdirectory.
3456 **Example:**
3457 ```tomo
3458 for p in (/tmp).walk()
3459 say("File or dir: $p")
3461 # The path itself is always included:
3462 assert [p for p in (./file.txt).walk()] == [(./file.txt)]
3464 ```
3465 ## Path.write
3467 ```tomo
3468 Path.write : func(path: Path, text: Text, permissions = Int32(0o644) -> Result)
3469 ```
3471 Writes the given text to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.
3473 Argument | Type | Description | Default
3474 ---------|------|-------------|---------
3475 path | `Path` | The path of the file to write to. | -
3476 text | `Text` | The text to write to the file. | -
3477 permissions | `` | The permissions to set on the file if it is created. | `Int32(0o644)`
3479 **Return:** Either `Success` or `Failure(reason)`.
3482 **Example:**
3483 ```tomo
3484 (./file.txt).write("Hello, world!")!
3486 ```
3487 ## Path.write_bytes
3489 ```tomo
3490 Path.write_bytes : func(path: Path, bytes: [Byte], permissions = Int32(0o644) -> Result)
3491 ```
3493 Writes the given bytes to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.
3495 Argument | Type | Description | Default
3496 ---------|------|-------------|---------
3497 path | `Path` | The path of the file to write to. | -
3498 bytes | `[Byte]` | A list of bytes to write to the file. | -
3499 permissions | `` | The permissions to set on the file if it is created. | `Int32(0o644)`
3501 **Return:** Either `Success` or `Failure(reason)`.
3504 **Example:**
3505 ```tomo
3506 (./file.txt).write_bytes([104, 105])!
3508 ```
3509 ## Path.write_unique
3511 ```tomo
3512 Path.write_unique : func(path: Path, text: Text -> Path)
3513 ```
3515 Writes the given text to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.
3517 Argument | Type | Description | Default
3518 ---------|------|-------------|---------
3519 path | `Path` | The base path for generating the unique file. This path must include the string `XXXXXX` in the file base name. | -
3520 text | `Text` | The text to write to the file. | -
3522 **Return:** The path of the newly created unique file.
3525 **Example:**
3526 ```tomo
3527 created := (./file-XXXXXX.txt).write_unique("Hello, world!")!
3528 assert created == (./file-27QHtq.txt)
3529 assert created.read()! == "Hello, world!"
3530 created.remove()!
3532 ```
3533 ## Path.write_unique_bytes
3535 ```tomo
3536 Path.write_unique_bytes : func(path: Path, bytes: [Byte] -> Path)
3537 ```
3539 Writes the given bytes to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.
3541 Argument | Type | Description | Default
3542 ---------|------|-------------|---------
3543 path | `Path` | The base path for generating the unique file. This path must include the string `XXXXXX` in the file base name. | -
3544 bytes | `[Byte]` | The bytes to write to the file. | -
3546 **Return:** The path of the newly created unique file.
3549 **Example:**
3550 ```tomo
3551 created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!
3552 assert created == (./file-27QHtq.txt)
3553 assert created.read_bytes()! == [1, 2, 3]
3554 created.remove()!
3556 ```
3557 ## Path.writer
3559 ```tomo
3560 Path.writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(text:Text, close:Bool=no -> Result))
3561 ```
3563 Returns a function that can be used to repeatedly write to the same file.
3565 The file writer will keep its file descriptor open after each write (unless the `close` argument is set to `yes`). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.
3567 Argument | Type | Description | Default
3568 ---------|------|-------------|---------
3569 path | `Path` | The path of the file to write to. | -
3570 append | `Bool` | If set to `yes`, writes to the file will append. If set to `no`, then the first write to the file will overwrite its contents and subsequent calls will append. | `no`
3571 permissions | `Int32` | The permissions to set on the file if it is created. | `Int32(0o644)`
3573 **Return:** Returns a function that can repeatedly write to the same file. If `close` is set to `yes`, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.
3576 **Example:**
3577 ```tomo
3578 write := (./file.txt).writer()
3579 write("Hello\n")!
3580 write("world\n", close=yes)!
3582 ```
3584 # Table
3585 ## Table.clear
3587 ```tomo
3588 Table.clear : func(t: &{K:V} -> Void)
3589 ```
3591 Removes all key-value pairs from the table.
3593 Argument | Type | Description | Default
3594 ---------|------|-------------|---------
3595 t | `&{K:V}` | The reference to the table. | -
3597 **Return:** Nothing.
3600 **Example:**
3601 ```tomo
3602 t := &{"A":1}
3603 t.clear()
3604 assert t[] == {}
3606 ```
3607 ## Table.difference
3609 ```tomo
3610 Table.difference : func(t: {K:V}, other: {K:V} -> {K:V})
3611 ```
3613 Return a table whose key/value pairs correspond to keys only present in one table, but not the other.
3615 Argument | Type | Description | Default
3616 ---------|------|-------------|---------
3617 t | `{K:V}` | The base table. | -
3618 other | `{K:V}` | The other table. | -
3620 **Return:** A table containing the common key/value pairs whose keys only appear in one table.
3623 **Example:**
3624 ```tomo
3625 t1 := {"A": 1, "B": 2, "C": 3}
3626 t2 := {"B": 2, "C":30, "D": 40}
3627 assert t1.difference(t2) == {"A": 1, "D": 40}
3629 ```
3630 ## Table.get
3632 ```tomo
3633 Table.get : func(t: {K:V}, key: K -> V?)
3634 ```
3636 Retrieves the value associated with a key, or returns `none` if the key is not present.
3638 Default values for the table are ignored.
3640 Argument | Type | Description | Default
3641 ---------|------|-------------|---------
3642 t | `{K:V}` | The table. | -
3643 key | `K` | The key whose associated value is to be retrieved. | -
3645 **Return:** The value associated with the key or `none` if the key is not found.
3648 **Example:**
3649 ```tomo
3650 t := {"A": 1, "B": 2}
3651 assert t.get("A") == 1
3652 assert t.get("????") == none
3653 assert t.get("A")! == 1
3654 assert t.get("????") or 0 == 0
3656 ```
3657 ## Table.get_or_set
3659 ```tomo
3660 Table.get_or_set : func(t: &{K:V}, key: K, default: V -> V?)
3661 ```
3663 If the given key is in the table, return the associated value. Otherwise, insert the given default value into the table and return it.
3665 If no default value is provided explicitly, but the table has a default value associated with it, the table's default value will be used.
3666 The default value is only evaluated if the key is missing.
3668 Argument | Type | Description | Default
3669 ---------|------|-------------|---------
3670 t | `&{K:V}` | The table. | -
3671 key | `K` | The key whose associated value is to be retrieved. | -
3672 default | `V` | The default value to insert and return if the key is not present in the table. | -
3674 **Return:** Either the value associated with the key (if present) or the default value. The table will be mutated if the key is not already present.
3677 **Example:**
3678 ```tomo
3679 t := &{"A": @[1, 2, 3]; default=@[]}
3680 t.get_or_set("A").insert(4)
3681 t.get_or_set("B").insert(99)
3682 assert t["A"][] == [1, 2, 3, 4]
3683 assert t["B"][] == [99]
3684 assert t.get_or_set("C", @[0, 0, 0])[] == [0, 0, 0]
3686 ```
3687 ## Table.has
3689 ```tomo
3690 Table.has : func(t: {K:V}, key: K -> Bool)
3691 ```
3693 Checks if the table contains a specified key.
3695 Argument | Type | Description | Default
3696 ---------|------|-------------|---------
3697 t | `{K:V}` | The table. | -
3698 key | `K` | The key to check for presence. | -
3700 **Return:** `yes` if the key is present, `no` otherwise.
3703 **Example:**
3704 ```tomo
3705 assert {"A": 1, "B": 2}.has("A") == yes
3706 assert {"A": 1, "B": 2}.has("xxx") == no
3708 ```
3709 ## Table.intersection
3711 ```tomo
3712 Table.intersection : func(t: {K:V}, other: {K:V} -> {K:V})
3713 ```
3715 Return a table with only the matching key/value pairs that are common to both tables.
3717 Argument | Type | Description | Default
3718 ---------|------|-------------|---------
3719 t | `{K:V}` | The base table. | -
3720 other | `{K:V}` | The other table. | -
3722 **Return:** A table containing the common key/value pairs shared between two tables.
3725 **Example:**
3726 ```tomo
3727 t1 := {"A": 1, "B": 2, "C": 3}
3728 t2 := {"B": 2, "C":30, "D": 40}
3729 assert t1.intersection(t2) == {"B": 2}
3731 ```
3732 ## Table.remove
3734 ```tomo
3735 Table.remove : func(t: {K:V}, key: K -> Void)
3736 ```
3738 Removes the key-value pair associated with a specified key.
3740 Argument | Type | Description | Default
3741 ---------|------|-------------|---------
3742 t | `{K:V}` | The reference to the table. | -
3743 key | `K` | The key of the key-value pair to remove. | -
3745 **Return:** Nothing.
3748 **Example:**
3749 ```tomo
3750 t := &{"A": 1, "B": 2}
3751 t.remove("A")
3752 assert t == {"B": 2}
3754 ```
3755 ## Table.set
3757 ```tomo
3758 Table.set : func(t: {K:V}, key: K, value: V -> Void)
3759 ```
3761 Sets or updates the value associated with a specified key.
3763 Argument | Type | Description | Default
3764 ---------|------|-------------|---------
3765 t | `{K:V}` | The reference to the table. | -
3766 key | `K` | The key to set or update. | -
3767 value | `V` | The value to associate with the key. | -
3769 **Return:** Nothing.
3772 **Example:**
3773 ```tomo
3774 t := &{"A": 1, "B": 2}
3775 t.set("C", 3)
3776 assert t == {"A": 1, "B": 2, "C": 3}
3778 ```
3779 ## Table.with
3781 ```tomo
3782 Table.with : func(t: {K:V}, other: {K:V} -> {K:V})
3783 ```
3785 Return a copy of a table with values added from another table
3787 Argument | Type | Description | Default
3788 ---------|------|-------------|---------
3789 t | `{K:V}` | The base table. | -
3790 other | `{K:V}` | The other table from which new key/value pairs will be added. | -
3792 **Return:** The original table, but with values from the other table added.
3795 **Example:**
3796 ```tomo
3797 t := {"A": 1, "B": 2}
3798 assert t.with({"B": 20, "C": 30}) == {"A": 1, "B": 20, "C": 30}
3800 ```
3801 ## Table.with_fallback
3803 ```tomo
3804 Table.with_fallback : func(t: {K:V}, fallback: {K:V}? -> {K:V})
3805 ```
3807 Return a copy of a table with a different fallback table.
3809 Argument | Type | Description | Default
3810 ---------|------|-------------|---------
3811 t | `{K:V}` | The table whose fallback will be replaced. | -
3812 fallback | `{K:V}?` | The new fallback table value. | -
3814 **Return:** The original table with a different fallback.
3817 **Example:**
3818 ```tomo
3819 t := {"A": 1; fallback={"B": 2}}
3820 t2 := t.with_fallback({"B": 3})
3821 assert t2["B"] == 3
3822 t3 := t.with_fallback(none)
3823 assert t3["B"] == none
3825 ```
3826 ## Table.without
3828 ```tomo
3829 Table.without : func(t: {K:V}, other: {K:V} -> {K:V})
3830 ```
3832 Return a copy of a table, but without any of the exact key/value pairs found in the other table.
3834 Only exact key/value pairs will be discarded. Keys with a non-matching value will be kept.
3836 Argument | Type | Description | Default
3837 ---------|------|-------------|---------
3838 t | `{K:V}` | The base table. | -
3839 other | `{K:V}` | The other table whose key/value pairs will be omitted. | -
3841 **Return:** The original table, but without the key/value pairs from the other table.
3844 **Example:**
3845 ```tomo
3846 t := {"A": 1, "B": 2, "C": 3}
3847 assert t.without({"B": 2, "C": 30, "D": 40}) == {"A": 1, "C": 3}
3849 ```
3851 # Text
3852 ## Text.as_c_string
3854 ```tomo
3855 Text.as_c_string : func(text: Text -> CString)
3856 ```
3858 Converts a `Text` value to a C-style string.
3860 Argument | Type | Description | Default
3861 ---------|------|-------------|---------
3862 text | `Text` | The text to be converted to a C-style string. | -
3864 **Return:** A C-style string (`CString`) representing the text.
3867 **Example:**
3868 ```tomo
3869 assert "Hello".as_c_string() == CString("Hello")
3871 ```
3872 ## Text.at
3874 ```tomo
3875 Text.at : func(text: Text, index: Int -> Text)
3876 ```
3878 Get the graphical cluster at a given index. This is similar to `str[i]` with ASCII text, but has more correct behavior for unicode text.
3880 Negative indices are counted from the back of the text, so `-1` means the last cluster, `-2` means the second-to-last, and so on.
3882 Argument | Type | Description | Default
3883 ---------|------|-------------|---------
3884 text | `Text` | The text from which to get a cluster. | -
3885 index | `Int` | The index of the graphical cluster (1-indexed). | -
3887 **Return:** A `Text` with the single graphical cluster at the given index.
3890 **Example:**
3891 ```tomo
3892 assert "Amélie".at(3) == "é"
3894 ```
3895 ## Text.by_line
3897 ```tomo
3898 Text.by_line : func(text: Text -> func(->Text?))
3899 ```
3901 Returns an iterator function that can be used to iterate over the lines in a text.
3903 This function ignores a trailing newline if there is one. If you don't want this behavior, use `text.by_split($/{1 nl}/)` instead.
3905 Argument | Type | Description | Default
3906 ---------|------|-------------|---------
3907 text | `Text` | The text to be iterated over, line by line. | -
3909 **Return:** An iterator function that returns one line at a time, until it runs out and returns `none`.
3912 **Example:**
3913 ```tomo
3914 text := "
3915 line one
3916 line two
3918 lines := [line for line in text.by_line()]
3919 assert lines == ["line one", "line two"]
3921 ```
3922 ## Text.by_split
3924 ```tomo
3925 Text.by_split : func(text: Text, delimiter: Text = "" -> func(->Text?))
3926 ```
3928 Returns an iterator function that can be used to iterate over text separated by a delimiter.
3930 To split based on a set of delimiters, use Text.by_split_any().
3931 If an empty text is given as the delimiter, then each split will be the graphical clusters of the text.
3933 Argument | Type | Description | Default
3934 ---------|------|-------------|---------
3935 text | `Text` | The text to be iterated over in delimited chunks. | -
3936 delimiter | `Text` | An exact delimiter to use for splitting the text. | `""`
3938 **Return:** An iterator function that returns one chunk of text at a time, separated by the given delimiter, until it runs out and returns `none`.
3941 **Example:**
3942 ```tomo
3943 text := "one,two,three"
3944 chunks := [chunk for chunk in text.by_split(",")]
3945 assert chunks == ["one", "two", "three"]
3947 ```
3948 ## Text.by_split_any
3950 ```tomo
3951 Text.by_split_any : func(text: Text, delimiters: Text = " $\t\r\n" -> func(->Text?))
3952 ```
3954 Returns an iterator function that can be used to iterate over text separated by one or more characters (grapheme clusters) from a given text of delimiters.
3956 Splitting will occur on every place where one or more of the grapheme clusters in `delimiters` occurs.
3957 To split based on an exact delimiter, use Text.by_split().
3959 Argument | Type | Description | Default
3960 ---------|------|-------------|---------
3961 text | `Text` | The text to be iterated over in delimited chunks. | -
3962 delimiters | `Text` | Grapheme clusters to use for splitting the text. | `" $\t\r\n"`
3964 **Return:** An iterator function that returns one chunk of text at a time, separated by the given delimiter characters, until it runs out and returns `none`.
3967 **Example:**
3968 ```tomo
3969 text := "one,two,;,three"
3970 chunks := [chunk for chunk in text.by_split_any(",;")]
3971 assert chunks == ["one", "two", "three"]
3973 ```
3974 ## Text.caseless_equals
3976 ```tomo
3977 Text.caseless_equals : func(a: Text, b: Text, language: Text = "C" -> Bool)
3978 ```
3980 Checks whether two texts are equal, ignoring the casing of the letters (i.e. case-insensitive comparison).
3982 Argument | Type | Description | Default
3983 ---------|------|-------------|---------
3984 a | `Text` | The first text to compare case-insensitively. | -
3985 b | `Text` | The second text to compare case-insensitively. | -
3986 language | `Text` | The ISO 639 language code for which casing rules to use. | `"C"`
3988 **Return:** `yes` if `a` and `b` are equal to each other, ignoring casing, otherwise `no`.
3991 **Example:**
3992 ```tomo
3993 assert "A".caseless_equals("a") == yes
3995 # Turkish lowercase "I" is "ı" (dotless I), not "i"
3996 assert "I".caseless_equals("i", language="tr_TR") == no
3998 ```
3999 ## Text.codepoint_names
4001 ```tomo
4002 Text.codepoint_names : func(text: Text -> [Text])
4003 ```
4005 Returns a list of the names of each codepoint in the text.
4007 Argument | Type | Description | Default
4008 ---------|------|-------------|---------
4009 text | `Text` | The text from which to extract codepoint names. | -
4011 **Return:** A list of codepoint names (`[Text]`).
4014 **Example:**
4015 ```tomo
4016 assert "Amélie".codepoint_names() == [
4017 "LATIN CAPITAL LETTER A",
4018 "LATIN SMALL LETTER M",
4019 "LATIN SMALL LETTER E WITH ACUTE",
4020 "LATIN SMALL LETTER L",
4021 "LATIN SMALL LETTER I",
4022 "LATIN SMALL LETTER E",
4025 ```
4026 ## Text.distance
4028 ```tomo
4029 Text.distance : func(a: Text, b: Text, language: Text = "C" -> Num)
4030 ```
4032 Get an approximate distance between two texts, such that when the distance is small, the texts are similar and when the distance is large, the texts are dissimilar.
4034 The exact distance algorithm is not specified and may be subject to change over time.
4036 Argument | Type | Description | Default
4037 ---------|------|-------------|---------
4038 a | `Text` | The first text to compare. | -
4039 b | `Text` | The second text to compare. | -
4040 language | `Text` | The ISO 639 language code for which character width to use. | `"C"`
4042 **Return:** The distance between the two texts (larger means more dissimilar).
4045 **Example:**
4046 ```tomo
4047 assert "hello".distance("hello") == 0
4048 texts := &["goodbye", "hello", "hallo"]
4049 texts.sort(func(a,b:&Text) a.distance("hello") <> b.distance("hello"))
4050 assert texts == ["hello", "hallo", "goodbye"]
4052 ```
4053 ## Text.ends_with
4055 ```tomo
4056 Text.ends_with : func(text: Text, suffix: Text, remainder: &Text? = none -> Bool)
4057 ```
4059 Checks if the `Text` ends with a literal suffix text.
4061 Argument | Type | Description | Default
4062 ---------|------|-------------|---------
4063 text | `Text` | The text to be searched. | -
4064 suffix | `Text` | The literal suffix text to check for. | -
4065 remainder | `&Text?` | If non-none, this value will be set to the rest of the text up to the trailing suffix. If the suffix is not found, this value will be set to the original text. | `none`
4067 **Return:** `yes` if the text has the target, `no` otherwise.
4070 **Example:**
4071 ```tomo
4072 assert "hello world".ends_with("world") == yes
4073 remainder : Text
4074 assert "hello world".ends_with("world", &remainder) == yes
4075 assert remainder == "hello "
4077 ```
4078 ## Text.find
4080 ```tomo
4081 Text.find : func(text: Text, target: Text, start: Int = 1 -> Int)
4082 ```
4084 Find a substring within a text and return its index, if found.
4086 Argument | Type | Description | Default
4087 ---------|------|-------------|---------
4088 text | `Text` | The text to be searched. | -
4089 target | `Text` | The target text to find. | -
4090 start | `Int` | The index at which to begin searching. | `1`
4092 **Return:** The index where the first occurrence of `target` appears, or `none` if it is not found.
4095 **Example:**
4096 ```tomo
4097 assert "one two".find("one") == 1
4098 assert "one two".find("two") == 5
4099 assert "one two".find("three") == none
4100 assert "one two".find("o", start=2) == 7
4102 ```
4103 ## Text.from
4105 ```tomo
4106 Text.from : func(text: Text, first: Int -> Text)
4107 ```
4109 Get a slice of the text, starting at the given position.
4111 A negative index counts backwards from the end of the text, so `-1` refers to the last cluster, `-2` the second-to-last, etc. Slice ranges will be truncated to the length of the text.
4113 Argument | Type | Description | Default
4114 ---------|------|-------------|---------
4115 text | `Text` | The text to be sliced. | -
4116 first | `Int` | The index to begin the slice. | -
4118 **Return:** The text from the given grapheme cluster to the end of the text.
4121 **Example:**
4122 ```tomo
4123 assert "hello".from(2) == "ello"
4124 assert "hello".from(-2) == "lo"
4126 ```
4127 ## Text.from_c_string
4129 ```tomo
4130 Text.from_c_string : func(str: CString -> Text)
4131 ```
4133 Converts a C-style string to a `Text` value.
4135 Argument | Type | Description | Default
4136 ---------|------|-------------|---------
4137 str | `CString` | The C-style string to be converted. | -
4139 **Return:** A `Text` value representing the C-style string.
4142 **Example:**
4143 ```tomo
4144 assert Text.from_c_string(CString("Hello")) == "Hello"
4146 ```
4147 ## Text.from_codepoint_names
4149 ```tomo
4150 Text.from_codepoint_names : func(codepoint_names: [Text] -> [Text])
4151 ```
4153 Returns text that has the given codepoint names (according to the Unicode specification) as its codepoints.
4155 The text will be normalized, so the resulting text's codepoints may not exactly match the input codepoints.
4157 Argument | Type | Description | Default
4158 ---------|------|-------------|---------
4159 codepoint_names | `[Text]` | The names of each codepoint in the desired text (case-insentive). | -
4161 **Return:** A new text with the specified codepoints after normalization has been applied. Any invalid names are ignored.
4164 **Example:**
4165 ```tomo
4166 text := Text.from_codepoint_names([
4167 "LATIN CAPITAL LETTER A WITH RING ABOVE",
4168 "LATIN SMALL LETTER K",
4169 "LATIN SMALL LETTER E",
4171 assert text == "Åke"
4173 ```
4174 ## Text.from_utf16
4176 ```tomo
4177 Text.from_utf16 : func(bytes: [Int16] -> [Text])
4178 ```
4180 Returns text that has been constructed from the given UTF16 sequence.
4182 The text will be normalized, so the resulting text's UTF16 sequence may not exactly match the input.
4184 Argument | Type | Description | Default
4185 ---------|------|-------------|---------
4186 bytes | `[Int16]` | The UTF-16 integers of the desired text. | -
4188 **Return:** A new text based on the input UTF16 sequence after normalization has been applied.
4191 **Example:**
4192 ```tomo
4193 assert Text.from_utf16([197, 107, 101]) == "Åke"
4194 assert Text.from_utf16([12371, 12435, 12395, 12385, 12399, 19990, 30028]) == "こんにちは世界"
4196 ```
4197 ## Text.from_utf32
4199 ```tomo
4200 Text.from_utf32 : func(codepoints: [Int32] -> [Text])
4201 ```
4203 Returns text that has been constructed from the given UTF32 codepoints.
4205 The text will be normalized, so the resulting text's codepoints may not exactly match the input codepoints.
4207 Argument | Type | Description | Default
4208 ---------|------|-------------|---------
4209 codepoints | `[Int32]` | The UTF32 codepoints in the desired text. | -
4211 **Return:** A new text with the specified codepoints after normalization has been applied.
4214 **Example:**
4215 ```tomo
4216 assert Text.from_utf32([197, 107, 101]) == "Åke"
4218 ```
4219 ## Text.from_utf8
4221 ```tomo
4222 Text.from_utf8 : func(bytes: [Byte] -> [Text])
4223 ```
4225 Returns text that has been constructed from the given UTF8 bytes.
4227 The text will be normalized, so the resulting text's UTF8 bytes may not exactly match the input.
4229 Argument | Type | Description | Default
4230 ---------|------|-------------|---------
4231 bytes | `[Byte]` | The UTF-8 bytes of the desired text. | -
4233 **Return:** A new text based on the input UTF8 bytes after normalization has been applied.
4236 **Example:**
4237 ```tomo
4238 assert Text.from_utf8([195, 133, 107, 101]) == "Åke"
4240 ```
4241 ## Text.has
4243 ```tomo
4244 Text.has : func(text: Text, target: Text -> Bool)
4245 ```
4247 Checks if the `Text` contains some target text.
4249 Argument | Type | Description | Default
4250 ---------|------|-------------|---------
4251 text | `Text` | The text to be searched. | -
4252 target | `Text` | The text to search for. | -
4254 **Return:** `yes` if the target text is found, `no` otherwise.
4257 **Example:**
4258 ```tomo
4259 assert "hello world".has("wo") == yes
4260 assert "hello world".has("xxx") == no
4262 ```
4263 ## Text.join
4265 ```tomo
4266 Text.join : func(glue: Text, pieces: [Text] -> Text)
4267 ```
4269 Joins a list of text pieces with a specified glue.
4271 Argument | Type | Description | Default
4272 ---------|------|-------------|---------
4273 glue | `Text` | The text used to join the pieces. | -
4274 pieces | `[Text]` | The list of text pieces to be joined. | -
4276 **Return:** A single `Text` value with the pieces joined by the glue.
4279 **Example:**
4280 ```tomo
4281 assert ", ".join(["one", "two", "three"]) == "one, two, three"
4283 ```
4284 ## Text.left_pad
4286 ```tomo
4287 Text.left_pad : func(text: Text, width: Int, pad: Text = " ", language: Text = "C" -> Text)
4288 ```
4290 Pad some text on the left side so it reaches a target width.
4292 Argument | Type | Description | Default
4293 ---------|------|-------------|---------
4294 text | `Text` | The text to pad. | -
4295 width | `Int` | The target width. | -
4296 pad | `Text` | The padding text. | `" "`
4297 language | `Text` | The ISO 639 language code for which character width to use. | `"C"`
4299 **Return:** Text with length at least `width`, with extra padding on the left as needed. If `pad` has length greater than 1, it may be partially repeated to reach the exact desired length.
4302 **Example:**
4303 ```tomo
4304 assert "x".left_pad(5) == " x"
4305 assert "x".left_pad(5, "ABC") == "ABCAx"
4307 ```
4308 ## Text.lines
4310 ```tomo
4311 Text.lines : func(text: Text -> [Text])
4312 ```
4314 Splits the text into a list of lines of text, preserving blank lines, ignoring trailing newlines, and handling `\r\n` the same as `\n`.
4316 Argument | Type | Description | Default
4317 ---------|------|-------------|---------
4318 text | `Text` | The text to be split into lines. | -
4320 **Return:** A list of substrings resulting from the split.
4323 **Example:**
4324 ```tomo
4325 assert "one\ntwo\nthree".lines() == ["one", "two", "three"]
4326 assert "one\ntwo\nthree\n".lines() == ["one", "two", "three"]
4327 assert "one\ntwo\nthree\n\n".lines() == ["one", "two", "three", ""]
4328 assert "one\r\ntwo\r\nthree\r\n".lines() == ["one", "two", "three"]
4329 assert "".lines() == []
4331 ```
4332 ## Text.lower
4334 ```tomo
4335 Text.lower : func(text: Text, language: Text = "C" -> Text)
4336 ```
4338 Converts all characters in the text to lowercase.
4340 Argument | Type | Description | Default
4341 ---------|------|-------------|---------
4342 text | `Text` | The text to be converted to lowercase. | -
4343 language | `Text` | The ISO 639 language code for which casing rules to use. | `"C"`
4345 **Return:** The lowercase version of the text.
4348 **Example:**
4349 ```tomo
4350 assert "AMÉLIE".lower() == "amélie"
4351 assert "I".lower(language="tr_TR") == "ı"
4353 ```
4354 ## Text.matches_glob
4356 ```tomo
4357 Text.matches_glob : func(path: Text, glob: Text -> Bool)
4358 ```
4360 Return whether or not the text matches the given glob.
4362 Argument | Type | Description | Default
4363 ---------|------|-------------|---------
4364 path | `Text` | The text to check. | -
4365 glob | `Text` | The glob pattern to check. | -
4367 **Return:** Whether or not the text matches the given glob.
4370 **Example:**
4371 ```tomo
4372 assert "hello world".matches_glob("h* *d")
4374 ```
4375 ## Text.middle_pad
4377 ```tomo
4378 Text.middle_pad : func(text: Text, width: Int, pad: Text = " ", language: Text = "C" -> Text)
4379 ```
4381 Pad some text on the left and right side so it reaches a target width.
4383 Argument | Type | Description | Default
4384 ---------|------|-------------|---------
4385 text | `Text` | The text to pad. | -
4386 width | `Int` | The target width. | -
4387 pad | `Text` | The padding text. | `" "`
4388 language | `Text` | The ISO 639 language code for which character width to use. | `"C"`
4390 **Return:** Text with length at least `width`, with extra padding on the left and right as needed. If `pad` has length greater than 1, it may be partially repeated to reach the exact desired length.
4393 **Example:**
4394 ```tomo
4395 assert "x".middle_pad(6) == " x "
4396 assert "x".middle_pad(10, "ABC") == "ABCAxABCAB"
4398 ```
4399 ## Text.quoted
4401 ```tomo
4402 Text.quoted : func(text: Text, color: Bool = no, quotation_mark: Text = `"` -> Text)
4403 ```
4405 Formats the text with quotation marks and escapes.
4407 Argument | Type | Description | Default
4408 ---------|------|-------------|---------
4409 text | `Text` | The text to be quoted. | -
4410 color | `Bool` | Whether to add color formatting. | `no`
4411 quotation_mark | `Text` | The quotation mark to use. | ``"``
4413 **Return:** The text formatted as a quoted text.
4416 **Example:**
4417 ```tomo
4418 assert "one\ntwo".quoted() == "\"one\\ntwo\""
4420 ```
4421 ## Text.repeat
4423 ```tomo
4424 Text.repeat : func(text: Text, count: Int -> Text)
4425 ```
4427 Repeat some text multiple times.
4429 Argument | Type | Description | Default
4430 ---------|------|-------------|---------
4431 text | `Text` | The text to repeat. | -
4432 count | `Int` | The number of times to repeat it. (Negative numbers are equivalent to zero). | -
4434 **Return:** The text repeated the given number of times.
4437 **Example:**
4438 ```tomo
4439 assert "Abc".repeat(3) == "AbcAbcAbc"
4441 ```
4442 ## Text.replace
4444 ```tomo
4445 Text.replace : func(text: Text, target: Text, replacement: Text -> Text)
4446 ```
4448 Replaces occurrences of a target text with a replacement text.
4450 Argument | Type | Description | Default
4451 ---------|------|-------------|---------
4452 text | `Text` | The text in which to perform replacements. | -
4453 target | `Text` | The target text to be replaced. | -
4454 replacement | `Text` | The text to replace the target with. | -
4456 **Return:** The text with occurrences of the target replaced.
4459 **Example:**
4460 ```tomo
4461 assert "Hello world".replace("world", "there") == "Hello there"
4463 ```
4464 ## Text.reversed
4466 ```tomo
4467 Text.reversed : func(text: Text -> Text)
4468 ```
4470 Return a text that has the grapheme clusters in reverse order.
4472 Argument | Type | Description | Default
4473 ---------|------|-------------|---------
4474 text | `Text` | The text to reverse. | -
4476 **Return:** A reversed version of the text.
4479 **Example:**
4480 ```tomo
4481 assert "Abc".reversed() == "cbA"
4483 ```
4484 ## Text.right_pad
4486 ```tomo
4487 Text.right_pad : func(text: Text, width: Int, pad: Text = " ", language: Text = "C" -> Text)
4488 ```
4490 Pad some text on the right side so it reaches a target width.
4492 Argument | Type | Description | Default
4493 ---------|------|-------------|---------
4494 text | `Text` | The text to pad. | -
4495 width | `Int` | The target width. | -
4496 pad | `Text` | The padding text. | `" "`
4497 language | `Text` | The ISO 639 language code for which character width to use. | `"C"`
4499 **Return:** Text with length at least `width`, with extra padding on the right as needed. If `pad` has length greater than 1, it may be partially repeated to reach the exact desired length.
4502 **Example:**
4503 ```tomo
4504 assert "x".right_pad(5) == "x "
4505 assert "x".right_pad(5, "ABC") == "xABCA"
4507 ```
4508 ## Text.slice
4510 ```tomo
4511 Text.slice : func(text: Text, from: Int = 1, to: Int = -1 -> Text)
4512 ```
4514 Get a slice of the text.
4516 A negative index counts backwards from the end of the text, so `-1` refers to the last cluster, `-2` the second-to-last, etc. Slice ranges will be truncated to the length of the text.
4518 Argument | Type | Description | Default
4519 ---------|------|-------------|---------
4520 text | `Text` | The text to be sliced. | -
4521 from | `Int` | The index of the first grapheme cluster to include (1-indexed). | `1`
4522 to | `Int` | The index of the last grapheme cluster to include (1-indexed). | `-1`
4524 **Return:** The text that spans the given grapheme cluster indices.
4527 **Example:**
4528 ```tomo
4529 assert "hello".slice(2, 3) == "el"
4530 assert "hello".slice(to=-2) == "hell"
4531 assert "hello".slice(from=2) == "ello"
4533 ```
4534 ## Text.split
4536 ```tomo
4537 Text.split : func(text: Text, delimiter: Text = "" -> [Text])
4538 ```
4540 Splits the text into a list of substrings based on exact matches of a delimiter.
4542 To split based on a set of delimiters, use Text.split_any().
4543 If an empty text is given as the delimiter, then each split will be the graphical clusters of the text.
4545 Argument | Type | Description | Default
4546 ---------|------|-------------|---------
4547 text | `Text` | The text to be split. | -
4548 delimiter | `Text` | The delimiter used to split the text. | `""`
4550 **Return:** A list of subtexts resulting from the split.
4553 **Example:**
4554 ```tomo
4555 assert "one,two,,three".split(",") == ["one", "two", "", "three"]
4556 assert "abc".split() == ["a", "b", "c"]
4558 ```
4559 ## Text.split_any
4561 ```tomo
4562 Text.split_any : func(text: Text, delimiters: Text = " $\t\r\n" -> [Text])
4563 ```
4565 Splits the text into a list of substrings at one or more occurrences of a set of delimiter characters (grapheme clusters).
4567 Splitting will occur on every place where one or more of the grapheme clusters in `delimiters` occurs.
4568 To split based on an exact delimiter, use Text.split().
4570 Argument | Type | Description | Default
4571 ---------|------|-------------|---------
4572 text | `Text` | The text to be split. | -
4573 delimiters | `Text` | A text containing delimiters to use for splitting the text. | `" $\t\r\n"`
4575 **Return:** A list of subtexts resulting from the split.
4578 **Example:**
4579 ```tomo
4580 assert "one, two,,three".split_any(", ") == ["one", "two", "three"]
4582 ```
4583 ## Text.starts_with
4585 ```tomo
4586 Text.starts_with : func(text: Text, prefix: Text, remainder: &Text? = none -> Bool)
4587 ```
4589 Checks if the `Text` starts with a literal prefix text.
4591 Argument | Type | Description | Default
4592 ---------|------|-------------|---------
4593 text | `Text` | The text to be searched. | -
4594 prefix | `Text` | The literal prefix text to check for. | -
4595 remainder | `&Text?` | If non-none, this value will be set to the rest of the text after the prefix. If the prefix is not found, this value will be set to the original text. | `none`
4597 **Return:** `yes` if the text has the given prefix, `no` otherwise.
4600 **Example:**
4601 ```tomo
4602 assert "hello world".starts_with("hello") == yes
4603 remainder : Text
4604 assert "hello world".starts_with("hello", &remainder) == yes
4605 assert remainder == " world"
4607 ```
4608 ## Text.title
4610 ```tomo
4611 Text.title : func(text: Text, language: Text = "C" -> Text)
4612 ```
4614 Converts the text to title case (capitalizing the first letter of each word).
4616 Argument | Type | Description | Default
4617 ---------|------|-------------|---------
4618 text | `Text` | The text to be converted to title case. | -
4619 language | `Text` | The ISO 639 language code for which casing rules to use. | `"C"`
4621 **Return:** The text in title case.
4624 **Example:**
4625 ```tomo
4626 assert "amélie".title() == "Amélie"
4628 # In Turkish, uppercase "i" is "İ"
4629 assert "i".title(language="tr_TR") == "İ"
4631 ```
4632 ## Text.to
4634 ```tomo
4635 Text.to : func(text: Text, last: Int -> Text)
4636 ```
4638 Get a slice of the text, ending at the given position.
4640 A negative index counts backwards from the end of the text, so `-1` refers to the last cluster, `-2` the second-to-last, etc. Slice ranges will be truncated to the length of the text.
4642 Argument | Type | Description | Default
4643 ---------|------|-------------|---------
4644 text | `Text` | The text to be sliced. | -
4645 last | `Int` | The index of the last grapheme cluster to include (1-indexed). | -
4647 **Return:** The text up to and including the given grapheme cluster.
4650 **Example:**
4651 ```tomo
4652 assert "goodbye".to(3) == "goo"
4653 assert "goodbye".to(-2) == "goodby"
4655 ```
4656 ## Text.translate
4658 ```tomo
4659 Text.translate : func(text: Text, translations: {Text:Text} -> Text)
4660 ```
4662 Takes a table mapping target texts to their replacements and performs all the replacements in the table on the whole text. At each position, the first matching replacement is applied and the matching moves on to *after* the replacement text, so replacement text is not recursively modified. See Text.replace() for more information about replacement behavior.
4664 Argument | Type | Description | Default
4665 ---------|------|-------------|---------
4666 text | `Text` | The text to be translated. | -
4667 translations | `{Text:Text}` | A table mapping from target text to its replacement. | -
4669 **Return:** The text with all occurrences of the targets replaced with their corresponding replacement text.
4672 **Example:**
4673 ```tomo
4674 text := "A <tag> & an ampersand".translate({
4675 "&": "&amp;",
4676 "<": "&lt;",
4677 ">": "&gt;",
4678 '"': "&quot",
4679 "'": "&#39;",
4681 assert text == "A &lt;tag&gt; &amp; an ampersand"
4683 ```
4684 ## Text.trim
4686 ```tomo
4687 Text.trim : func(text: Text, to_trim: Text = " $\t\r\n", left: Bool = yes, right: Bool = yes -> Text)
4688 ```
4690 Trims the given characters (grapheme clusters) from the left and/or right side of the text.
4692 Argument | Type | Description | Default
4693 ---------|------|-------------|---------
4694 text | `Text` | The text to be trimmed. | -
4695 to_trim | `Text` | The characters to remove from the left/right of the text. | `" $\t\r\n"`
4696 left | `Bool` | Whether or not to trim from the front of the text. | `yes`
4697 right | `Bool` | Whether or not to trim from the back of the text. | `yes`
4699 **Return:** The text without the trim characters at either end.
4702 **Example:**
4703 ```tomo
4704 assert " x y z \n".trim() == "x y z"
4705 assert "one,".trim(",") == "one"
4706 assert " xyz ".trim(right=no) == "xyz "
4708 ```
4709 ## Text.upper
4711 ```tomo
4712 Text.upper : func(text: Text, language: Text = "C" -> Text)
4713 ```
4715 Converts all characters in the text to uppercase.
4717 Argument | Type | Description | Default
4718 ---------|------|-------------|---------
4719 text | `Text` | The text to be converted to uppercase. | -
4720 language | `Text` | The ISO 639 language code for which casing rules to use. | `"C"`
4722 **Return:** The uppercase version of the text.
4725 **Example:**
4726 ```tomo
4727 assert "amélie".upper() == "AMÉLIE"
4729 # In Turkish, uppercase "i" is "İ"
4730 assert "i".upper(language="tr_TR") == "İ"
4732 ```
4733 ## Text.utf16
4735 ```tomo
4736 Text.utf16 : func(text: Text -> [Int16])
4737 ```
4739 Returns a list of Unicode code points for UTF16 encoding of the text.
4741 Argument | Type | Description | Default
4742 ---------|------|-------------|---------
4743 text | `Text` | The text from which to extract Unicode code points. | -
4745 **Return:** A list of 16-bit integer Unicode code points (`[Int16]`).
4748 **Example:**
4749 ```tomo
4750 assert "Åke".utf16() == [197, 107, 101]
4751 assert "こんにちは世界".utf16() == [12371, 12435, 12395, 12385, 12399, 19990, 30028]
4753 ```
4754 ## Text.utf32
4756 ```tomo
4757 Text.utf32 : func(text: Text -> [Int32])
4758 ```
4760 Returns a list of Unicode code points for UTF32 encoding of the text.
4762 Argument | Type | Description | Default
4763 ---------|------|-------------|---------
4764 text | `Text` | The text from which to extract Unicode code points. | -
4766 **Return:** A list of 32-bit integer Unicode code points (`[Int32]`).
4769 **Example:**
4770 ```tomo
4771 assert "Amélie".utf32() == [65, 109, 233, 108, 105, 101]
4773 ```
4774 ## Text.utf8
4776 ```tomo
4777 Text.utf8 : func(text: Text -> [Byte])
4778 ```
4780 Converts a `Text` value to a list of bytes representing a UTF8 encoding of the text.
4782 Argument | Type | Description | Default
4783 ---------|------|-------------|---------
4784 text | `Text` | The text to be converted to UTF8 bytes. | -
4786 **Return:** A list of bytes (`[Byte]`) representing the text in UTF8 encoding.
4789 **Example:**
4790 ```tomo
4791 assert "Amélie".utf8() == [65, 109, 195, 169, 108, 105, 101]
4793 ```
4794 ## Text.width
4796 ```tomo
4797 Text.width : func(text: Text -> Int)
4798 ```
4800 Returns the display width of the text as seen in a terminal with appropriate font rendering. This is usually the same as the text's `.length`, but there are some characters like emojis that render wider than 1 cell.
4802 This will not always be exactly accurate when your terminal's font rendering can't handle some unicode displaying correctly.
4804 Argument | Type | Description | Default
4805 ---------|------|-------------|---------
4806 text | `Text` | The text whose length you want. | -
4808 **Return:** An integer representing the display width of the text.
4811 **Example:**
4812 ```tomo
4813 assert "Amélie".width() == 6
4814 assert "🤠".width() == 2
4816 ```
4817 ## Text.without_prefix
4819 ```tomo
4820 Text.without_prefix : func(text: Text, prefix: Text -> Text)
4821 ```
4823 Returns the text with a given prefix removed (if present).
4825 Argument | Type | Description | Default
4826 ---------|------|-------------|---------
4827 text | `Text` | The text to remove the prefix from. | -
4828 prefix | `Text` | The prefix to remove. | -
4830 **Return:** A text without the given prefix (if present) or the unmodified text if the prefix is not present.
4833 **Example:**
4834 ```tomo
4835 assert "foo:baz".without_prefix("foo:") == "baz"
4836 assert "qux".without_prefix("foo:") == "qux"
4838 ```
4839 ## Text.without_suffix
4841 ```tomo
4842 Text.without_suffix : func(text: Text, suffix: Text -> Text)
4843 ```
4845 Returns the text with a given suffix removed (if present).
4847 Argument | Type | Description | Default
4848 ---------|------|-------------|---------
4849 text | `Text` | The text to remove the suffix from. | -
4850 suffix | `Text` | The suffix to remove. | -
4852 **Return:** A text without the given suffix (if present) or the unmodified text if the suffix is not present.
4855 **Example:**
4856 ```tomo
4857 assert "baz.foo".without_suffix(".foo") == "baz"
4858 assert "qux".without_suffix(".foo") == "qux"
4860 ```