llm
Download
6082 lines 155.5 KiBMarkdownModified 2026-09-02 raw

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)
)

breakpoint

breakpoint : func(-> Void)

Stops the program in a debugger at the point where it is called. Running the program under tomo run --debug gives a debugger prompt here, showing the surrounding source and the values of the variables in scope.

Only a program compiled with --debug contains this call at all. Without that flag it compiles to nothing, so a breakpoint() left in the source costs a release build nothing and does nothing if the program is run outside a debugger. See docs/debugging.md.

Return: Nothing.

Example:

total := 0
for i in 10
    total += i
breakpoint() # `tomo run --debug` stops here, with `total` and `i` in scope

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. The accepted values are yes/no, true/false, on/off, and 1/0, each written in lowercase (true), uppercase (TRUE), or capitalized (True). Mixed casings like tRuE are not accepted.

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 not Byte(6).get_bit(1)
assert Byte(6).get_bit(2)
assert Byte(6).get_bit(3)
assert not Byte(6).get_bit(4)

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)
assert Byte(7).is_between(10, 1)
assert not Byte(7).is_between(100, 200)
assert Byte(7).is_between(1, 7)

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. This is the same conversion that Text(str) performs.

A C string is an arbitrary sequence of non-NUL bytes, but Text holds Unicode, so this returns none when the bytes are not valid UTF-8.

Argument Type Description Default
str CString The C string. -

Return: The C string as a Text, or none if it is not valid UTF-8.

Example:

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

CString.bytes

CString.bytes : func(str: CString -> [Byte])

Convert a C string to a list of its raw bytes.

Argument Type Description Default
str CString The C string. -

Return: A list of bytes ([Byte]) representing the C string's contents.

Example:

assert CString("Hi").bytes() == [72, 105]

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")

Float64

Float64.1_PI

Float64.1_PI : Float64

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

Float64.2_PI

Float64.2_PI : Float64

The constant $2 \times \pi$.

Float64.2_SQRTPI

Float64.2_SQRTPI : Float64

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

Float64.E

Float64.E : Float64

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

Float64.INF

Float64.INF : Float64

Positive infinity.

Float64.LN10

Float64.LN10 : Float64

The natural logarithm of 10.

Float64.LN2

Float64.LN2 : Float64

The natural logarithm of 2.

Float64.LOG2E

Float64.LOG2E : Float64

The base 2 logarithm of $e$

Float64.PI

Float64.PI : Float64

Pi ($\pi$).

Float64.PI_2

Float64.PI_2 : Float64

$\frac{\pi}{2}$

Float64.PI_4

Float64.PI_4 : Float64

$\frac{\pi}{4}$

Float64.SQRT1_2

Float64.SQRT1_2 : Float64

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

Float64.SQRT2

Float64.SQRT2 : Float64

$\sqrt{2}$

Float64.TAU

Float64.TAU : Float64

Tau ($2 \times \pi$)

Float64.abs

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

Calculates the absolute value of a number.

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

Return: The absolute value of n.

Example:

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

Float64.acos

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

Computes the arc cosine of a number.

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

Return: The arc cosine of x in radians.

Example:

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

Float64.acosh

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

Computes the inverse hyperbolic cosine of a number.

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

Return: The inverse hyperbolic cosine of x.

Example:

assert Float64(1.0).acosh() == 0

Float64.asin

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

Computes the arc sine of a number.

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

Return: The arc sine of x in radians.

Example:

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

Float64.asinh

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

Computes the inverse hyperbolic sine of a number.

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

Return: The inverse hyperbolic sine of x.

Example:

assert Float64(0.0).asinh() == 0

Float64.atan

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

Computes the arc tangent of a number.

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

Return: The arc tangent of x in radians.

Example:

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

Float64.atan2

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

Computes the arc tangent of the quotient of two numbers.

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

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

Example:

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

Float64.atanh

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

Computes the inverse hyperbolic tangent of a number.

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

Return: The inverse hyperbolic tangent of x.

Example:

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

Float64.cbrt

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

Computes the cube root of a number.

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

Return: The cube root of x.

Example:

assert Float64(27.0).cbrt() == 3

Float64.ceil

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

Rounds a number up to the nearest integer.

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

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

Example:

assert Float64(3.2).ceil() == 4

Float64.clamped

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

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

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

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

Example:

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

Float64.copysign

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

Copies the sign of one number to another.

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

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

Example:

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

Float64.cos

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

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

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

Return: The cosine of x.

Example:

assert Float64(0.0).cos() == 1

Float64.cosh

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

Computes the hyperbolic cosine of a number.

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

Return: The hyperbolic cosine of x.

Example:

assert Float64(0.0).cosh() == 1

Float64.erf

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

Computes the error function of a number.

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

Return: The error function of x.

Example:

assert Float64(0.0).erf() == 0

Float64.erfc

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

Computes the complementary error function of a number.

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

Return: The complementary error function of x.

Example:

assert Float64(0.0).erfc() == 1

Float64.exp

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

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

Argument Type Description Default
x Float64 The exponent. -

Return: The value of $e^x$.

Example:

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

Float64.exp2

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

Computes $2^x$ for a number.

Argument Type Description Default
x Float64 The exponent. -

Return: The value of $2^x$.

Example:

assert Float64(3.0).exp2() == 8

Float64.expm1

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

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

Argument Type Description Default
x Float64 The exponent. -

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

Example:

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

Float64.fdim

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

Computes the positive difference between two numbers.

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

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

Example:

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

Float64.floor

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

Rounds a number down to the nearest integer.

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

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

Example:

assert Float64(3.7).floor() == 3

Float64.hypot

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

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

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

Return: The Euclidean norm of x and y.

Example:

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

Float64.is_between

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

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

Argument Type Description Default
x Float64 The integer to be checked. -
low Float64 One end of the range to check (inclusive). -
high Float64 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 Float64(7.5).is_between(1, 10)
assert Float64(7.5).is_between(10, 1)
assert not Float64(7.5).is_between(100, 200)
assert Float64(7.5).is_between(1, 7.5)

Float64.isfinite

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

Checks if a number is finite.

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

Return: yes if n is finite, no otherwise.

Example:

assert Float64(1.0).isfinite()
assert not Float64.INF.isfinite()

Float64.isinf

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

Checks if a number is infinite.

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

Return: yes if n is infinite, no otherwise.

Example:

assert Float64.INF.isinf()
assert not Float64(1.0).isinf()

Float64.j0

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

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

Argument Type Description Default
x Float64 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 Float64(0.0).j0() == 1

Float64.j1

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

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

Argument Type Description Default
x Float64 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 Float64(0.0).j1() == 0

Float64.log

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

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

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

Return: The natural logarithm of x.

Example:

assert Float64.E.log() == 1

Float64.log10

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

Computes the base-10 logarithm of a number.

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

Return: The base-10 logarithm of x.

Example:

assert Float64(100.0).log10() == 2

Float64.log1p

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

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

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

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

Example:

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

Float64.log2

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

Computes the base-2 logarithm of a number.

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

Return: The base-2 logarithm of x.

Example:

assert Float64(8.0).log2() == 3

Float64.logb

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

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

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

Return: The binary exponent of x.

Example:

assert Float64(8.0).logb() == 3

Float64.mix

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

Interpolates between two numbers based on a given amount.

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

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

Example:

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

Float64.near

Float64.near : func(x: Float64, y: Float64, ratio: Float64 = 1e-9, min_epsilon: Float64 = 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 Float64 The first number. -
y Float64 The second number. -
ratio Float64 The relative tolerance. Default is 1e-9. 1e-9
min_epsilon Float64 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 Float64(1.0).near(1.000000001)
assert Float64(100.0).near(110, ratio=0.1)
assert Float64(5.0).near(5.1, min_epsilon=0.1)

Float64.nextafter

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

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

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

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

Example:

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

Float64.parse

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

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 Float64.parse("3.14") == 3.14
assert Float64.parse("1e3") == 1000
assert Float64.parse("1.5junk") == none
remainder : Text
assert Float64.parse("1.5junk", &remainder) == 1.5
assert remainder == "junk"

Float64.percent

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

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

Argument Type Description Default
n Float64 The number to be converted to a percent. -
precision Float64 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 Float64(0.5).percent() == "50%"
assert (Float64(1.) / Float64(3.)).percent(2) == "34%"
assert (Float64(1.) / Float64(3.)).percent(precision=0.0001) == "33.3333%"
assert (Float64(1.) / Float64(3.)).percent(precision=10.) == "30%"

Float64.rint

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

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

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

Return: The nearest integer value of x.

Example:

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

Float64.round

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

Rounds a number to the nearest whole number integer.

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

Return: The nearest integer value of x.

Example:

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

Float64.significand

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

Extracts the significand (or mantissa) of a number.

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

Return: The significand of x.

Example:

assert Float64(1234.567).significand() == 1.2056318359375

Float64.sin

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

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

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

Return: The sine of x.

Example:

assert Float64(0.0).sin() == 0

Float64.sinh

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

Computes the hyperbolic sine of a number.

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

Return: The hyperbolic sine of x.

Example:

assert Float64(0.0).sinh() == 0

Float64.sqrt

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

Computes the square root of a number.

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

Return: The square root of x.

Example:

assert Float64(16.0).sqrt() == 4

Float64.tan

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

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

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

Return: The tangent of x.

Example:

assert Float64(0.0).tan() == 0

Float64.tanh

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

Computes the hyperbolic tangent of a number.

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

Return: The hyperbolic tangent of x.

Example:

assert Float64(0.0).tanh() == 0

Float64.tgamma

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

Computes the gamma function of a number.

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

Return: The gamma function of x.

Example:

assert Float64(1.0).tgamma() == 1

Float64.trunc

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

Truncates a number to the nearest integer towards zero.

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

Return: The integer part of x towards zero.

Example:

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

Float64.with_precision

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

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

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

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

Example:

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

Float64.y0

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

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

Argument Type Description Default
x Float64 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 Float64(1.0).y0().near(0.08825696421567698)

Float64.y1

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

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

Argument Type Description Default
x Float64 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 Float64(1.0).y1().near(-0.7812128213002887)

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 not 6.get_bit(1)
assert 6.get_bit(2)
assert 6.get_bit(3)
assert not 6.get_bit(4)

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)
assert 7.is_between(10, 1)
assert not 7.is_between(100, 200)
assert 7.is_between(1, 7)

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()
assert not 6.is_prime()

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)
    break 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 : func(list: [T], predicate: func(x:T->Bool) -> Int)

Performs a binary search on a sorted list.

Argument Type Description Default
list [T] The sorted list to search. -
predicate func(x:T->Bool) The predicate to look for in the list. -

Return: Find the first item in the list where the predicate function is true and return its index (or none if no such item exists). This assumes that the predicate function is monotonic over the list's contents. In other words, the predicate is false for the first zero or more items in the list and then true for the remainder of the list.

Example:

# Find an item:
assert [10, 20, 30, 40].binary_search(func(x:Int) x == 30) == 3
# No such item:
assert [10, 20, 30, 40].binary_search(func(x:Int) x == 25) == none
# Find an insertion point (where an item would go to preserve sort order):
assert [10, 20, 30, 40].binary_search(func(x:Int) x >= 25) == 3

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)

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.pairs

List.pairs : func(list: [T] -> func(a:&T, b:&T -> Bool))

Returns an iterator that yields each unordered pair of distinct elements exactly once (equivalent to iterating a at index i and b at every later index j > i). The iterator yields two values per iteration, so a loop over it binds two variables: for a, b in list.pairs(). Mutating the list after making the iterator does not affect what it yields.

Argument Type Description Default
list [T] The list whose element pairs will be iterated. -

Return: An iterator function that yields each pair of elements.

Example:

assert ["$a$b" for a, b in [1, 2, 3].pairs()] == ["12", "13", "23"]

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.swap

List.swap : func(list: @[T], i: Int, j: Int -> Void)

Swaps the elements at two indices in place. Compiles inline, so a swap costs one bounds check per index and a single copy-on-write check (a two-element multi-assignment swap pays both twice). Swapping an index with itself is a no-op. Negative indices count from the back of the list, and an out-of-bounds index is a runtime error.

Argument Type Description Default
list @[T] The mutable reference to the list. -
i Int The index of the first element (1-indexed). -
j Int The index of the second element (1-indexed). -

Return: Nothing.

Example:

list := &[10, 20, 30]
list.swap(1, 3)
assert list == [30, 20, 10]

list.swap(2, -1)
assert list == [30, 10, 20]

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.PI

Num.PI : Num

The ratio of a circle's circumference to its diameter, held exactly rather than as an approximation.

Example:

assert Num.PI.sin() == 0
assert Num.PI.digits(10) == "3.1415926535…"

Num.TAU

Num.TAU : Num

Two times pi, held exactly.

Example:

assert Num.TAU == 2 * Num.PI

Num.abs

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

The absolute value of a number.

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

Return: The absolute value of x.

Example:

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

Num.acos

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

The arc cosine of a number, in radians.

Argument Type Description Default
x Num The number whose arc cosine is to be computed. -

Return: The arc cosine of x, or none if x is outside [-1, 1].

Example:

assert (1.).acos()! == 0
assert (2.).acos() == none

Num.asin

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

The arc sine of a number, in radians.

Argument Type Description Default
x Num The number whose arc sine is to be computed. -

Return: The arc sine of x, or none if x is outside [-1, 1].

Example:

assert (0.).asin()! == 0
assert (2.).asin() == none

Num.atan

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

The arc tangent of a number, in radians. Defined for every number.

Argument Type Description Default
x Num The number whose arc tangent is to be computed. -

Return: The arc tangent of x.

Example:

assert (0.).atan() == 0
assert (1.).atan() == Num.PI / 4

Num.atan2

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

The angle of the point (x, y), in radians, placed in the correct quadrant by the signs of both arguments.

Argument Type Description Default
y Num The y coordinate. -
x Num The x coordinate. -

Return: The angle in (-pi, pi], or none at the origin, where no angle is defined.

Example:

assert (1.).atan2(1)! == Num.PI / 4
assert (0.).atan2(0) == none

Num.ceil

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

The smallest whole number greater than or equal to a number.

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

Return: x rounded up.

Example:

assert (4.2).ceil() == 5
assert (-4.2).ceil() == -4

Num.clamped

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

A number restricted to a range.

Argument Type Description Default
x Num The number to clamp. -
low Num The lowest allowed value. -
high Num The highest allowed value. -

Return: x, or the nearer of low and high if x falls outside them.

Example:

assert (1.5).clamped(0, 1) == 1
assert (0.5).clamped(0, 1) == 0.5

Num.cos

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

The cosine of an angle in radians.

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

Return: The cosine of x.

Example:

assert (0.).cos() == 1
assert Num.PI.cos() == -1

Num.cosh

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

The hyperbolic cosine of a number.

Argument Type Description Default
x Num The number whose hyperbolic cosine is to be computed. -

Return: The hyperbolic cosine of x.

Example:

assert (0.).cosh() == 1

Num.digits

Num.digits : func(n: Num, digits: Int = 15, ellipsis: Text = "…" -> Text)

The decimal expansion of a number, to at most the requested number of fractional digits. A value that fits exactly stops early rather than padding with zeros, and gets no marker. A value that doesn't shows a truncated prefix of its true expansion with the ellipsis appended, and never a rounding: every digit shown is a digit the value actually has. To round, round first.

Argument Type Description Default
n Num The number to expand. -
digits Int The maximum number of fractional digits. 15
ellipsis Text Appended when the digits don't capture the value exactly. "…"

Return: The decimal expansion as text.

Example:

assert (1/3).digits(10) == "0.3333333333…"
assert Num.PI.digits(10) == "3.1415926535…"
assert (2/3).digits(10, ellipsis="") == "0.6666666666"
assert (0.25).digits(10) == "0.25"

Num.exp

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

e raised to the given power.

Argument Type Description Default
x Num The exponent. -

Return: e to the power of x.

Example:

assert (0.).exp() == 1

Num.floor

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

The largest whole number less than or equal to a number.

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

Return: x rounded down.

Example:

assert (4.8).floor() == 4
assert (-4.2).floor() == -5

Num.gcd

Num.gcd : func(x: Num, y: Num -> Num?)

The greatest common divisor of two numbers, generalized to fractions: the largest value by which both can be divided to give whole numbers.

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

Return: The greatest common divisor, or none if either argument is irrational and so has no such divisor.

Example:

assert (12.).gcd(18)! == 6
assert (1./2.).gcd(1./3.)! == 1./6.

Num.inverse

Num.inverse : func(x: Num -> Num?)

One divided by a number.

Argument Type Description Default
x Num The number to invert. -

Return: The reciprocal of x, or none if x is zero.

Example:

assert (4.).inverse()! == 0.25
assert (0.).inverse() == none

Num.is_between

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

Whether a number lies within a range, inclusive.

Argument Type Description Default
x Num The number to check. -
low Num The lower bound. -
high Num The upper bound. -

Return: yes if low <= x <= high.

Example:

assert (0.5).is_between(0, 1)
assert not (1.5).is_between(0, 1)

Num.is_exact

Num.is_exact : func(n: Num, digits: Int = 15 -> Bool)

Whether the requested number of fractional digits represents a number exactly, rather than rounding it.

Argument Type Description Default
n Num The number to check. -
digits Int The number of fractional digits. 15

Return: yes if :digits(digits) is the value itself.

Example:

assert (0.25).is_exact(10)
assert not (1./3.).is_exact(10)

Num.is_integer

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

Whether a number is a whole number.

Argument Type Description Default
n Num The number to check. -

Return: yes if n has no fractional part.

Example:

assert (4.).is_integer()
assert not (4.5).is_integer()

Num.is_rational

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

Whether a number can be written exactly as a fraction, as opposed to an irrational value like the square root of two.

Argument Type Description Default
n Num The number to check. -

Return: yes if n is rational.

Example:

assert (1./3.).is_rational()
assert not (2.).sqrt()!.is_rational()

Num.lcm

Num.lcm : func(x: Num, y: Num -> Num?)

The least common multiple of two numbers, generalized to fractions.

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

Return: The least common multiple, or none if either argument is irrational.

Example:

assert (4.).lcm(6)! == 12

Num.log

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

The natural logarithm of a number.

Argument Type Description Default
x Num The number whose logarithm is to be computed. -

Return: The natural log of x, or none if x is not positive.

Example:

assert (1.).log()! == 0
assert (0.).log() == none

Num.log10

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

The base-10 logarithm of a number.

Argument Type Description Default
x Num The number whose logarithm is to be computed. -

Return: The base-10 log of x, or none if x is not positive.

Example:

assert (100.).log10()! == 2

Num.log2

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

The base-2 logarithm of a number.

Argument Type Description Default
x Num The number whose logarithm is to be computed. -

Return: The base-2 log of x, or none if x is not positive.

Example:

assert (8.).log2()! == 3
assert (1./4.).log2()! == -2

Num.max

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

The larger of two numbers.

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

Return: Whichever of x and y is larger.

Example:

assert (0.3).max(0.5) == 0.5

Num.min

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

The smaller of two numbers.

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

Return: Whichever of x and y is smaller.

Example:

assert (0.3).min(0.5) == 0.3

Num.mix

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

A point between two numbers, exactly. amount of zero gives x, one gives y, and a half gives the true midpoint.

Argument Type Description Default
amount Num How far from x toward y. -
x Num The value at amount zero. -
y Num The value at amount one. -

Return: The interpolated value.

Example:

assert (0.25).mix(10, 20) == 12.5
assert (1./3.).mix(0, 1) == 1./3.

Num.parse

Num.parse : func(text: Text -> Num?)

The exact number a piece of text denotes. Both decimals and fractions are accepted, and both are read exactly: "0.1" is a tenth, not the nearest float to one.

Argument Type Description Default
text Text The text to parse. -

Return: The number, or none if the text isn't one.

Example:

assert Num.parse("0.1")! == 0.1
assert Num.parse("22/7")! == 22./7.
assert Num.parse("nope") == none

Num.percent

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

A number as a percentage, rounded to the given precision.

Argument Type Description Default
n Num The number to format. -
precision Num Round the percentage to this precision. 1%

Return: The percentage, with a percent sign.

Example:

assert (0.5).percent() == "50%"
assert (1./3.).percent() == "33%"
assert (1./3.).percent(0.01%) == "33.33%"

Num.round

Num.round : func(x: Num, increment: Num = 1 -> Num)

The nearest multiple of an increment, exactly: the nearest penny, nickel, third, or thousand are all one argument away, and the default increment of 1 gives the nearest whole number. Ties go to the even multiple.

Argument Type Description Default
x Num The number to round. -
increment Num The step to round to a multiple of. Rounding to zero is an error. 1

Return: x rounded to the nearest multiple of increment.

Example:

assert (4.6).round() == 5
assert (2.5).round() == 2
assert (3.14159).round(0.01) == 3.14
assert (0.13).round(0.05) == 0.15
assert (0.5).round(1/3) == 2/3
assert (1234567.).round(1000) == 1235000

Num.sin

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

The sine of an angle in radians.

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

Return: The sine of x.

Example:

assert (0.).sin() == 0
assert Num.PI.sin() == 0

Num.sinh

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

The hyperbolic sine of a number.

Argument Type Description Default
x Num The number whose hyperbolic sine is to be computed. -

Return: The hyperbolic sine of x.

Example:

assert (0.).sinh() == 0

Num.sqrt

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

The square root of a number, exactly. The result of a non-square stays symbolic, so identities like sqrt(2) * sqrt(2) == 2 hold.

Argument Type Description Default
x Num The number whose square root is to be computed. -

Return: The square root of x, or none if x is negative.

Example:

assert (16.).sqrt()! == 4
assert (2.).sqrt()! * (2.).sqrt()! == 2
assert (-1.).sqrt() == none

Num.symbolic

Num.symbolic : func(n: Num -> Text)

The exact value written out: a whole number, a fraction, or a symbolic expression for an irrational.

Argument Type Description Default
n Num The number to write out. -

Return: The exact form.

Example:

assert (1./3.).symbolic() == "1/3"
assert (2.).sqrt()!.symbolic() == "sqrt(2)"
assert Num.PI.symbolic() == "pi"

Num.tan

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

The tangent of an angle in radians.

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

Return: The tangent of x, or none at a pole.

Example:

assert (0.).tan()! == 0

Num.tanh

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

The hyperbolic tangent of a number.

Argument Type Description Default
x Num The number whose hyperbolic tangent is to be computed. -

Return: The hyperbolic tangent of x.

Example:

assert (0.).tanh() == 0

Num.tex

Num.tex : func(n: Num -> Text)

The exact value as TeX math-mode source.

Argument Type Description Default
n Num The number to render. -

Return: The TeX source.

Example:

assert (1./3.).tex() == "\\frac{1}{3}"
assert (2.).sqrt()!.tex() == "\\sqrt{2}"

Num.trunc

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

The whole part of a number, discarding the fraction.

Argument Type Description Default
x Num The number to truncate. -

Return: x with its fractional part removed.

Example:

assert (4.8).trunc() == 4
assert (-4.8).trunc() == -4

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.

A POSIX filename is an arbitrary sequence of bytes, but Text holds Unicode, so this returns none when the name is not valid UTF-8.

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

Return: The base name of the file or directory, or none if it is not valid UTF-8.

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.bytes

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

Convert a path to a list of the raw bytes that make up its text representation. This does not read the file at the given path; see Path.read_bytes for that.

Argument Type Description Default
path Path The path. -

Return: A list of bytes ([Byte]) representing the path's text.

Example:

assert (/foo/bar).bytes() == [47, 102, 111, 111, 47, 98, 97, 114]

Path.can_execute

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

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

This answers about the moment it is asked, and another process can change it immediately after. Do not use it to decide whether an operation will succeed: attempt the operation and handle its Failure instead.

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()
assert not (/usr/include/stdlib.h).can_execute()
assert not (/non/existant/file).can_execute()

Path.can_read

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

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

This answers about the moment it is asked, and another process can change it immediately after. Do not use it to decide whether an operation will succeed: attempt the operation and handle its Failure instead.

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()
assert not (/etc/shadow).can_read()
assert not (/non/existant/file).can_read()

Path.can_write

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

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

This answers about the moment it is asked, and another process can change it immediately after. Do not use it to decide whether an operation will succeed: attempt the operation and handle its Failure instead.

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()
assert not (/etc/passwd).can_write()
assert not (/non/existant/file).can_write()

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: Bool = 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.

The paths returned keep the form of the path they came from: the children of (./foo) are relative and the children of (~/foo) stay home-based. Use .resolved() on them if you need absolute paths.

Returns none if the path is not a readable directory.

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 paths for the children, or none if the directory could not be read. An existing but empty directory gives an empty list, not none.

Example:

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

# A directory that can't be read gives `none`, not an empty list:
assert (./not-a-directory).children() == none

Path.components

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

Returns a list of the file components of a path.

A POSIX filename is an arbitrary sequence of bytes, but Text holds Unicode, so this returns none when the name is not valid UTF-8.

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

Return: Each of the file components of the path in a list, or none if any component is not valid UTF-8. Note: for absolute paths, the first component will be "/". Trailing slashes are ignored.

Example:

assert (./foo/baz.txt).components() == [".", "foo", "baz.txt"]
assert (/absolute/path/).components() == ["/", "absolute", "path"]

Path.concatenated_with

Path.concatenated_with : func(a: Path, b: Path -> Path)

Return the concatenation of two paths. This is what the ++ operator does on paths. The result is normalized, so . and .. components in the second path are resolved away.

Argument Type Description Default
a Path The base path. -
b Path A relative path to append. It is a runtime error if this is an absolute or home-based path. -

Return: The second path appended to the first.

Example:

assert (/foo/bar).concatenated_with((./baz)) == (/foo/bar/baz)
assert ((/foo/bar) ++ (./baz/../qux)) == (/foo/bar/qux)

Path.copy_to

Path.copy_to : func(path: Path, dest: Path, overwrite: Bool = no -> Result)

Copies the file or directory from one location to another. This is the same behavior as cp -rn -T src dest or cp -rf -T src dest (if overwrite is enabled).

Copying a tree is many operations rather than one, so unlike Path.move this cannot be indivisible. With overwrite=no an existing destination is never written over, but if one appears while the copy is running it is skipped silently rather than reported.

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

Return: Either Success or Failure{reason}.

Example:

(./file.txt).copy_to(/tmp/copy.txt)!

Path.create_directory

Path.create_directory : func(path: Path, permissions: Int32 = Int32(0o755), recursive: Bool = 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.

A directory that already exists is a success, which is what makes this safe to call when another process may be creating the same directory. Something that exists but is not a directory is a failure.

Argument Type Description Default
path Path The path of the directory to create. -
permissions Int32 The permissions to set on the new directory. Int32(0o755)
recursive Bool 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)

Returns the absolute path of the current working directory.

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: Bool = 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.

The paths returned keep the form of the path they came from: the children of (./foo) are relative and the children of (~/foo) stay home-based. Use .resolved() on them if you need absolute paths.

Returns none if the path is not a readable directory.

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: An iterator over the children in a directory, or none if the directory could not be read.

Example:

# Safely handle the directory not being readable:
if children := (/dir).each_child()
    for child in children
        say("Child: $child")
else
    say("Couldn't read the directory!")

# Assume the directory is readable and error if that's not the case:
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.

This answers about the moment it is asked. Deciding what to do from it races with anything else touching the filesystem; prefer operations that say what they did, such as Path.create_directory (which succeeds if the directory is already there) or Path.remove with ignore_missing.

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

Return: yes if the file or directory exists, otherwise no.

Example:

assert (/).exists()

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.

A name with no . in it has no extension, and gives none rather than an empty text. A leading . does not count, so a dotfile like (./.git) has no extension, and neither does a name ending in a ..

Also returns none when the name is not valid UTF-8, a POSIX filename being an arbitrary sequence of bytes while Text holds Unicode.

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 none if there is no extension.

Example:

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

# No "." in the name means no extension:
assert (/foo).extension() == none
assert (./.git).extension() == none
assert (./foo.).extension() == none

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.

The paths returned keep the form of the path they came from: the children of (./foo) are relative and the children of (~/foo) stay home-based. Use .resolved() on them if you need absolute paths.

Returns none if the path is not a readable directory.

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, or none if the directory could not be read. A directory with no files in it gives an empty list, not none.

Example:

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

Path.glob

Path.glob : func(path: Path, pattern: Text -> [Path]?)

Search a directory for paths matching a glob pattern. The pattern is relative to the directory, and unlike Path.matches_glob it is anchored: it has to account for every component below the directory.

Details of the pattern syntax:

  • ?, *, and character classes like [ch] match within a single component and never across a /.

  • Files or directories beginning with . will not match *, but will match .*. The paths "." and ".." are never included in the results.

  • ** stands for zero or more components, so "**/*.txt" finds .txt files at any depth. Unlike the other syntax, this cannot be answered by glob(3), so such a pattern is served by walking the directory tree. ** spans hidden components too, which is what makes it agree with Path.matches_glob. It does not descend through a symbolic link to a directory, since a link pointing back at an ancestor would never terminate; an explicit * component still matches one, so "*/x.txt" can find a file that "**/x.txt" will not.

  • The {a,b} alternation syntax is not supported. Results keep the form of the directory they came from, so globbing (./src) yields relative paths and globbing (~/src) yields home-based ones. Every path returned satisfies Path.matches_glob for the same pattern.

Returns none if the directory could not be read. A pattern that simply matches nothing gives an empty list, not none.

Argument Type Description Default
path Path The directory to search. -
pattern Text The glob pattern to match against, relative to the directory. An empty pattern matches nothing. -

Return: A sorted list of the paths that match, or none if the directory could not be read.

Example:

# A directory containing: foo.txt, baz.txt, qux.jpg, .hidden, sub/deep.txt
assert (./dir).glob("*.txt")! == [(./dir/baz.txt), (./dir/foo.txt)]
assert (./dir).glob(".*")! == [(./dir/.hidden)]
assert (./dir).glob("sub/*.txt")! == [(./dir/sub/deep.txt)]

# "**" is zero or more components:
assert (./dir).glob("**/*.txt")! == [(./dir/baz.txt), (./dir/foo.txt), (./dir/sub/deep.txt)]

# A pattern matching nothing is an empty list:
assert (./dir).glob("*.xxx")! == []

# A directory that can't be read is none:
assert (./not-a-directory).glob("*") == none

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. Unlike Path.extension, this reads the raw bytes of the name and so works on names that are not valid UTF-8.

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")
assert (/foo.txt).has_extension(".txt")
assert (/foo.tar.gz).has_extension("gz")
assert not (/foo.tar.gz).has_extension("zip")

# Asking for an empty extension is the same question as `.extension()`
# being `none`, for any name that is valid UTF-8:
assert (/foo).has_extension("")
assert (/).has_extension("")

Path.is_directory

Path.is_directory : func(path: Path, follow_symlinks: Bool = 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 Bool Whether to follow symbolic links. yes

Return: yes if the path is a directory, otherwise no.

Example:

assert (./directory/).is_directory()
assert not (./file.txt).is_directory()

Path.is_file

Path.is_file : func(path: Path, follow_symlinks: Bool = 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 Bool Whether to follow symbolic links. yes

Return: yes if the path is a file, otherwise no.

Example:

assert (./file.txt).is_file()
assert not (./directory/).is_file()

Path.is_pipe

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

Checks if the path represents a named pipe (a FIFO). Optionally follows symbolic links.

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

Return: yes if the path is a named pipe, otherwise no.

Example:

assert (./my-fifo).is_pipe()
assert not (./file.txt).is_pipe()

Path.is_socket

Path.is_socket : func(path: Path, follow_symlinks: Bool = 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 Bool Whether to follow symbolic links. yes

Return: yes if the path is a socket, otherwise no.

Example:

assert (./socket).is_socket()

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: yes if the path is a symbolic link, otherwise no.

Example:

assert (./link).is_symlink()

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. This is a pattern match, not a filesystem operation, and it reads the raw bytes of the path, so it works on names that are not valid UTF-8.

The pattern is split on / and matched against the path's components from the back, so a pattern matches any trailing run of components:

  • "*.txt" asks about the file's name wherever it sits, so it matches (./foo.txt), (/tmp/dir/foo.txt), and (~/foo.txt) alike. The answer does not depend on which form the path was written in.

  • "dir/*.txt" matches a .txt file directly inside any dir.

  • A pattern beginning with / can only line up at the front of the path, so "/tmp/*.txt" pins the whole path rather than matching a suffix. A pattern beginning with ./ likewise only matches ./-form paths.

  • ** stands for zero or more components, so "**/*.txt" matches a .txt file at any depth, including none.

  • ?, *, and character classes like [ch] match within a single component and never across a /. A . at the start of a component must be matched by a literal ., so * does not match hidden files.

  • The {a,b} alternation syntax is not supported.

An empty pattern matches nothing.

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:

# A bare pattern asks about the file's name, whatever form the path is in:
assert (./file.txt).matches_glob("*.txt")
assert (/tmp/dir/file.txt).matches_glob("*.txt")
assert not (./file.txt).matches_glob("*.jpg")

# More components match a longer suffix:
assert (./src/file.c).matches_glob("src/*.[ch]")
assert (./src/file.c).matches_glob("./src/*.[ch]")

# A leading "/" anchors the pattern to the whole path:
assert (/tmp/dir/file.txt).matches_glob("/tmp/dir/*.txt")
assert not (/other/dir/file.txt).matches_glob("/tmp/dir/*.txt")

# "**" is zero or more components:
assert (./a/b/c/file.txt).matches_glob("**/*.txt")
assert (./file.txt).matches_glob("**/*.txt")

# "*" does not match a leading "." or cross a "/":
assert not (./dir/.hidden).matches_glob("*")
assert (./dir/.hidden).matches_glob(".*")

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, overwrite: Bool = no -> Result)

Moves the file or directory from one location to another.

With overwrite=no, the refusal and the move are a single operation the kernel performs indivisibly, so another process cannot slip a file into the destination in between. Moving a directory across filesystems is the one case that cannot be done that way and falls back to checking first.

Argument Type Description Default
path Path The path to move. -
dest Path The destination to move the path to. -
overwrite Bool 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 -> Path)

Returns the path relative to a given base path.

The result has no leading ./, so a path naming something inside the base path cannot be written as a path literal. Results that climb out of the base path begin with ../ and can.

Argument Type Description Default
path Path The path to convert. -
relative_to Path The base path for the relative path. Unlike Path.resolved, this argument is required. -

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

Example:

# A path relative to itself is the current directory:
assert (/tmp).relative_to((/tmp)) == (.)
assert "$((./path/to/file.txt).relative_to((./path)))" == "to/file.txt"
assert "$((/tmp/foo).relative_to((/tmp)))" == "foo"
assert (/a/b/c).relative_to((/a/x)) == (../b/c)

Path.remove

Path.remove : func(path: Path, ignore_missing: Bool = 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 Bool 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 = (./) -> Path)

Resolves the absolute path of the given path relative to a base path. By default, the base path is the current directory. A relative base is itself resolved against the current directory first, so the result is always absolute.

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

Return: The resolved absolute path.

Example:

# Assume the current directory is /home/user
assert (~/foo).resolved() == (/home/user/foo)
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)

Returns none for a path with no parent to put a sibling beside, which is the file root (/).

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, or none if the path is (/).

Example:

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

Path.subdirectories

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

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

The paths returned keep the form of the path they came from: the children of (./foo) are relative and the children of (~/foo) stay home-based. Use .resolved() on them if you need absolute paths.

Returns none if the path is not a readable directory.

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

Return: A list of subdirectory paths, or none if the directory could not be read. A directory with no subdirectories gives an empty list, not none.

Example:

assert (./directory).subdirectories()!.sorted() == [(./directory/subdir1), (./directory/subdir2)]
assert (./directory).subdirectories(include_hidden=yes)!.sorted() == [(./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.

Returns none if the directory could not be created.

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, or none if it could not be created.

Example:

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

Path.walk

Path.walk : func(path: Path, include_hidden: Bool = 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. The paths returned keep the form of the path they came from: walking (./foo) yields relative paths and walking (~/foo) yields home-based ones.

Returns none if there is nothing at the given path. A path that exists but is not a directory walks over just itself.

Argument Type Description Default
path Path The path to begin the walk. -
include_hidden Bool 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, or none if the path does not exist.

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)]

# A path that isn't there has nothing to walk:
assert (./not-a-path).walk() == none

Path.with_extension

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

Return a path with the given file extension, either replacing the path's existing extension or adding to it.

Argument Type Description Default
path Path A path. -
extension Text The file extension to apply (a leading . is optional). If empty, the extension is removed entirely. -
replace Bool If yes, the path's existing extension is replaced. If no, the new extension is appended to the existing one. yes

Return: A new path with the requested extension.

Example:

assert (./file.tar.gz).with_extension("zip") == (./file.zip)
assert (./file.tar.gz).with_extension(".zip") == (./file.zip)
assert (./file.tar.gz).with_extension("") == (./file)
assert (./file.tar.gz).with_extension("zip", replace=no) == (./file.tar.gz.zip)
assert (./file).with_extension("txt") == (./file.txt)

Path.write

Path.write : func(path: Path, text: Text, permissions: Int32 = 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 Int32 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 = 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 Int32 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, or none if the file could not be created.

Example:

# The created path has the XXXXXX replaced by random characters,
# e.g. (./file-27QHtq.txt):
created := (./file-XXXXXX.txt).write_unique("Hello, world!")!
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, or none if the file could not be created.

Example:

# The created path has the XXXXXX replaced by random characters,
# e.g. (./file-27QHtq.txt):
created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!
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.entries

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

Returns an iterator that yields each key/value pair in the table, in insertion order. The iterator yields two values per iteration, so a loop over it binds two variables: for k, v in table.entries(). This is the only way to iterate a table's pairs (for k, v in table is a compile error); use the .keys or .values fields to iterate just one side. Mutating the table after making the iterator does not affect what it yields.

Argument Type Description Default
t {K:V} The table whose entries will be iterated. -

Return: An iterator function that yields each key/value pair.

Example:

t := {"A": 1, "B": 2}
assert ["$k=$v" for k, v in t.entries()] == ["A=1", "B=2"]

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")
assert not {"A": 1, "B": 2}.has("xxx")

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.

Returns none if the index is out of range. This is unlike text[i], which fails with an error instead of giving back a value.

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, or none if there is no cluster there.

Example:

assert "Amélie".at(3) == "é"
assert "Amélie".at(-1) == "e"
assert "Amélie".at(99) == none

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")

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

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 -> 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. -

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"]
assert "kitten".distance("sitting") == 3
assert "flaw".distance("lawn") == 2
# A transposition costs one edit, even when the texts differ in length:
assert "ab".distance("ba") == 1
assert "xab".distance("ba") == 2

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")
remainder : Text
assert "hello world".ends_with("world", &remainder)
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")
assert not "hello world".has("xxx")

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.nearest

Text.nearest : func(text: Text, candidates: [Text], max_distance: Num = 0.6 -> Text?)

Find which of candidates is most similar to this text, for suggesting a correction when a name isn't recognized. Similarity uses Text.distance(), and candidates that aren't close enough are ignored.

max_distance is an edit distance per grapheme, measured against the shorter of the two texts, so short texts have to match more closely than long ones. The default (0.6) accepts ordinary typos while rejecting unrelated short words.

Argument Type Description Default
text Text The text to find a match for. -
candidates [Text] The candidate texts to choose from. -
max_distance Num The maximum edit distance per grapheme of the shorter text. 0.6

Return: The closest candidate, or none if candidates is empty or nothing is within max_distance.

Example:

commands := ["build", "run", "test"]
assert "bulid".nearest(commands) == "build"
assert "frobnicate".nearest(commands) == none
assert "x".nearest([]) == none

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")
remainder : Text
assert "hello world".starts_with("hello", &remainder)
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"

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082
% API

# Builtins
## USE_COLOR

```tomo
USE_COLOR : Bool
```

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

## ask

```tomo
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:**
```tomo
assert ask("What's your name? ") == "Arthur Dent"

```
## at_cleanup

```tomo
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:**
```tomo
at_cleanup(func()
    _ := (/tmp/file.txt).remove(ignore_missing=yes)
)

```
## breakpoint

```tomo
breakpoint : func(-> Void)
```

Stops the program in a debugger at the point where it is called. Running the program under `tomo run --debug` gives a debugger prompt here, showing the surrounding source and the values of the variables in scope.

Only a program compiled with `--debug` contains this call at all. Without that flag it compiles to nothing, so a `breakpoint()` left in the source costs a release build nothing and does nothing if the program is run outside a debugger. See `docs/debugging.md`.


**Return:** Nothing.


**Example:**
```tomo
total := 0
for i in 10
    total += i
breakpoint() # `tomo run --debug` stops here, with `total` and `i` in scope

```
## exit

```tomo
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:**
```tomo
exit("Goodbye forever!", Int32(1))

```
## fail

```tomo
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:**
```tomo
fail("Oh no!")

```
## getenv

```tomo
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:**
```tomo
assert getenv("TERM") == "xterm-256color"
assert getenv("not_a_variable") == none

```
## print

```tomo
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:**
```tomo
print("Hello ", newline=no)
print("world!")

```
## say

```tomo
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:**
```tomo
say("Hello ", newline=no)
say("world!")

```
## setenv

```tomo
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:**
```tomo
setenv("FOOBAR", "xyz")

```
## sleep

```tomo
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:**
```tomo
sleep(1.5)

```

# Bool
## Bool.parse

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

Converts a text representation of a boolean value into a boolean. The accepted values are `yes`/`no`, `true`/`false`, `on`/`off`, and `1`/`0`, each written in lowercase (`true`), uppercase (`TRUE`), or capitalized (`True`). Mixed casings like `tRuE` are not accepted.

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:**
```tomo
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

```tomo
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:**
```tomo
assert not Byte(6).get_bit(1)
assert Byte(6).get_bit(2)
assert Byte(6).get_bit(3)
assert not Byte(6).get_bit(4)

```
## Byte.hex

```tomo
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:**
```tomo
assert Byte(18).hex(prefix=yes) == "0x12"

```
## Byte.is_between

```tomo
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:**
```tomo
assert Byte(7).is_between(1, 10)
assert Byte(7).is_between(10, 1)
assert not Byte(7).is_between(100, 200)
assert Byte(7).is_between(1, 7)

```
## Byte.parse

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
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

```tomo
CString.as_text : func(str: CString -> Text?)
```

Convert a C string to Text. This is the same conversion that `Text(str)` performs.

A C string is an arbitrary sequence of non-NUL bytes, but `Text` holds Unicode, so this returns `none` when the bytes are not valid UTF-8.

Argument | Type | Description | Default
---------|------|-------------|---------
str | `CString` | The C string.  | -

**Return:** The C string as a Text, or `none` if it is not valid UTF-8.


**Example:**
```tomo
assert CString("Hello").as_text() == "Hello"
assert Text(CString("Hello"))! == "Hello"

```
## CString.bytes

```tomo
CString.bytes : func(str: CString -> [Byte])
```

Convert a C string to a list of its raw bytes.

Argument | Type | Description | Default
---------|------|-------------|---------
str | `CString` | The C string.  | -

**Return:** A list of bytes (`[Byte]`) representing the C string's contents.


**Example:**
```tomo
assert CString("Hi").bytes() == [72, 105]

```
## CString.join

```tomo
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:**
```tomo
assert CString(",").join([CString("a"), CString("b")]) == CString("a,b")

```

# Float64
## Float64.1_PI

```tomo
Float64.1_PI : Float64
```

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

## Float64.2_PI

```tomo
Float64.2_PI : Float64
```

The constant $2 \times \pi$.

## Float64.2_SQRTPI

```tomo
Float64.2_SQRTPI : Float64
```

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

## Float64.E

```tomo
Float64.E : Float64
```

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

## Float64.INF

```tomo
Float64.INF : Float64
```

Positive infinity.

## Float64.LN10

```tomo
Float64.LN10 : Float64
```

The natural logarithm of 10.

## Float64.LN2

```tomo
Float64.LN2 : Float64
```

The natural logarithm of 2.

## Float64.LOG2E

```tomo
Float64.LOG2E : Float64
```

The base 2 logarithm of $e$

## Float64.PI

```tomo
Float64.PI : Float64
```

Pi ($\pi$).

## Float64.PI_2

```tomo
Float64.PI_2 : Float64
```

$\frac{\pi}{2}$

## Float64.PI_4

```tomo
Float64.PI_4 : Float64
```

$\frac{\pi}{4}$

## Float64.SQRT1_2

```tomo
Float64.SQRT1_2 : Float64
```

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

## Float64.SQRT2

```tomo
Float64.SQRT2 : Float64
```

$\sqrt{2}$

## Float64.TAU

```tomo
Float64.TAU : Float64
```

Tau ($2 \times \pi$)

## Float64.abs

```tomo
Float64.abs : func(n: Float64 -> Float64)
```

Calculates the absolute value of a number.

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

**Return:** The absolute value of `n`.


**Example:**
```tomo
assert Float64(-3.5).abs() == 3.5

```
## Float64.acos

```tomo
Float64.acos : func(x: Float64 -> Float64)
```

Computes the arc cosine of a number.

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

**Return:** The arc cosine of `x` in radians.


**Example:**
```tomo
assert Float64(0.0).acos().near(1.5707963267948966)

```
## Float64.acosh

```tomo
Float64.acosh : func(x: Float64 -> Float64)
```

Computes the inverse hyperbolic cosine of a number.

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

**Return:** The inverse hyperbolic cosine of `x`.


**Example:**
```tomo
assert Float64(1.0).acosh() == 0

```
## Float64.asin

```tomo
Float64.asin : func(x: Float64 -> Float64)
```

Computes the arc sine of a number.

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

**Return:** The arc sine of `x` in radians.


**Example:**
```tomo
assert Float64(0.5).asin().near(0.5235987755982989)

```
## Float64.asinh

```tomo
Float64.asinh : func(x: Float64 -> Float64)
```

Computes the inverse hyperbolic sine of a number.

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

**Return:** The inverse hyperbolic sine of `x`.


**Example:**
```tomo
assert Float64(0.0).asinh() == 0

```
## Float64.atan

```tomo
Float64.atan : func(x: Float64 -> Float64)
```

Computes the arc tangent of a number.

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

**Return:** The arc tangent of `x` in radians.


**Example:**
```tomo
assert Float64(1.0).atan().near(0.7853981633974483)

```
## Float64.atan2

```tomo
Float64.atan2 : func(x: Float64, y: Float64 -> Float64)
```

Computes the arc tangent of the quotient of two numbers.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The numerator.  | -
y | `Float64` | The denominator.  | -

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


**Example:**
```tomo
assert Float64.atan2(1, 1).near(0.7853981633974483)

```
## Float64.atanh

```tomo
Float64.atanh : func(x: Float64 -> Float64)
```

Computes the inverse hyperbolic tangent of a number.

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

**Return:** The inverse hyperbolic tangent of `x`.


**Example:**
```tomo
assert Float64(0.5).atanh().near(0.5493061443340549)

```
## Float64.cbrt

```tomo
Float64.cbrt : func(x: Float64 -> Float64)
```

Computes the cube root of a number.

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

**Return:** The cube root of `x`.


**Example:**
```tomo
assert Float64(27.0).cbrt() == 3

```
## Float64.ceil

```tomo
Float64.ceil : func(x: Float64 -> Float64)
```

Rounds a number up to the nearest integer.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The number to be rounded up.  | -

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


**Example:**
```tomo
assert Float64(3.2).ceil() == 4

```
## Float64.clamped

```tomo
Float64.clamped : func(x: Float64, low: Float64, high: Float64 -> Float64)
```

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

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

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


**Example:**
```tomo
assert Float64(2.5).clamped(5.5, 10.5) == 5.5

```
## Float64.copysign

```tomo
Float64.copysign : func(x: Float64, y: Float64 -> Float64)
```

Copies the sign of one number to another.

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

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


**Example:**
```tomo
assert Float64(3.0).copysign(-1) == -3

```
## Float64.cos

```tomo
Float64.cos : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The angle in radians.  | -

**Return:** The cosine of `x`.


**Example:**
```tomo
assert Float64(0.0).cos() == 1

```
## Float64.cosh

```tomo
Float64.cosh : func(x: Float64 -> Float64)
```

Computes the hyperbolic cosine of a number.

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

**Return:** The hyperbolic cosine of `x`.


**Example:**
```tomo
assert Float64(0.0).cosh() == 1

```
## Float64.erf

```tomo
Float64.erf : func(x: Float64 -> Float64)
```

Computes the error function of a number.

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

**Return:** The error function of `x`.


**Example:**
```tomo
assert Float64(0.0).erf() == 0

```
## Float64.erfc

```tomo
Float64.erfc : func(x: Float64 -> Float64)
```

Computes the complementary error function of a number.

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

**Return:** The complementary error function of `x`.


**Example:**
```tomo
assert Float64(0.0).erfc() == 1

```
## Float64.exp

```tomo
Float64.exp : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The exponent.  | -

**Return:** The value of $e^x$.


**Example:**
```tomo
assert Float64(1.0).exp().near(2.718281828459045)

```
## Float64.exp2

```tomo
Float64.exp2 : func(x: Float64 -> Float64)
```

Computes $2^x$ for a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The exponent.  | -

**Return:** The value of $2^x$.


**Example:**
```tomo
assert Float64(3.0).exp2() == 8

```
## Float64.expm1

```tomo
Float64.expm1 : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The exponent.  | -

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


**Example:**
```tomo
assert Float64(1.0).expm1().near(1.7182818284590453)

```
## Float64.fdim

```tomo
Float64.fdim : func(x: Float64, y: Float64 -> Float64)
```

Computes the positive difference between two numbers.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The first number.  | -
y | `Float64` | The second number.  | -

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


**Example:**
```tomo
assert Float64(5.0).fdim(3) == 2

```
## Float64.floor

```tomo
Float64.floor : func(x: Float64 -> Float64)
```

Rounds a number down to the nearest integer.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The number to be rounded down.  | -

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


**Example:**
```tomo
assert Float64(3.7).floor() == 3

```
## Float64.hypot

```tomo
Float64.hypot : func(x: Float64, y: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The first number.  | -
y | `Float64` | The second number.  | -

**Return:** The Euclidean norm of `x` and `y`.


**Example:**
```tomo
assert Float64.hypot(3, 4) == 5

```
## Float64.is_between

```tomo
Float64.is_between : func(x: Float64, low: Float64, high: Float64 -> Bool)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The integer to be checked.  | -
low | `Float64` | One end of the range to check (inclusive).  | -
high | `Float64` | 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:**
```tomo
assert Float64(7.5).is_between(1, 10)
assert Float64(7.5).is_between(10, 1)
assert not Float64(7.5).is_between(100, 200)
assert Float64(7.5).is_between(1, 7.5)

```
## Float64.isfinite

```tomo
Float64.isfinite : func(n: Float64 -> Bool)
```

Checks if a number is finite.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Float64` | The number to be checked.  | -

**Return:** `yes` if `n` is finite, `no` otherwise.


**Example:**
```tomo
assert Float64(1.0).isfinite()
assert not Float64.INF.isfinite()

```
## Float64.isinf

```tomo
Float64.isinf : func(n: Float64 -> Bool)
```

Checks if a number is infinite.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Float64` | The number to be checked.  | -

**Return:** `yes` if `n` is infinite, `no` otherwise.


**Example:**
```tomo
assert Float64.INF.isinf()
assert not Float64(1.0).isinf()

```
## Float64.j0

```tomo
Float64.j0 : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | 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:**
```tomo
assert Float64(0.0).j0() == 1

```
## Float64.j1

```tomo
Float64.j1 : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | 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:**
```tomo
assert Float64(0.0).j1() == 0

```
## Float64.log

```tomo
Float64.log : func(x: Float64 -> Float64)
```

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

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

**Return:** The natural logarithm of `x`.


**Example:**
```tomo
assert Float64.E.log() == 1

```
## Float64.log10

```tomo
Float64.log10 : func(x: Float64 -> Float64)
```

Computes the base-10 logarithm of a number.

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

**Return:** The base-10 logarithm of `x`.


**Example:**
```tomo
assert Float64(100.0).log10() == 2

```
## Float64.log1p

```tomo
Float64.log1p : func(x: Float64 -> Float64)
```

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

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

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


**Example:**
```tomo
assert Float64(1.0).log1p().near(0.6931471805599453)

```
## Float64.log2

```tomo
Float64.log2 : func(x: Float64 -> Float64)
```

Computes the base-2 logarithm of a number.

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

**Return:** The base-2 logarithm of `x`.


**Example:**
```tomo
assert Float64(8.0).log2() == 3

```
## Float64.logb

```tomo
Float64.logb : func(x: Float64 -> Float64)
```

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

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

**Return:** The binary exponent of `x`.


**Example:**
```tomo
assert Float64(8.0).logb() == 3

```
## Float64.mix

```tomo
Float64.mix : func(amount: Float64, x: Float64, y: Float64 -> Float64)
```

Interpolates between two numbers based on a given amount.

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

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


**Example:**
```tomo
assert Float64(0.5).mix(10, 20) == 15
assert Float64(0.25).mix(10, 20) == 12.5

```
## Float64.near

```tomo
Float64.near : func(x: Float64, y: Float64, ratio: Float64 = 1e-9, min_epsilon: Float64 = 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 | `Float64` | The first number.  | -
y | `Float64` | The second number.  | -
ratio | `Float64` | The relative tolerance. Default is `1e-9`.  | `1e-9`
min_epsilon | `Float64` | 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:**
```tomo
assert Float64(1.0).near(1.000000001)
assert Float64(100.0).near(110, ratio=0.1)
assert Float64(5.0).near(5.1, min_epsilon=0.1)

```
## Float64.nextafter

```tomo
Float64.nextafter : func(x: Float64, y: Float64 -> Float64)
```

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

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

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


**Example:**
```tomo
assert Float64(1.0).nextafter(1.1) == 1.0000000000000002

```
## Float64.parse

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

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:**
```tomo
assert Float64.parse("3.14") == 3.14
assert Float64.parse("1e3") == 1000
assert Float64.parse("1.5junk") == none
remainder : Text
assert Float64.parse("1.5junk", &remainder) == 1.5
assert remainder == "junk"

```
## Float64.percent

```tomo
Float64.percent : func(n: Float64, precision: Float64 = 0.01 -> Text)
```

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

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

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


**Example:**
```tomo
assert Float64(0.5).percent() == "50%"
assert (Float64(1.) / Float64(3.)).percent(2) == "34%"
assert (Float64(1.) / Float64(3.)).percent(precision=0.0001) == "33.3333%"
assert (Float64(1.) / Float64(3.)).percent(precision=10.) == "30%"

```
## Float64.rint

```tomo
Float64.rint : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The number to be rounded.  | -

**Return:** The nearest integer value of `x`.


**Example:**
```tomo
assert Float64(3.5).rint() == 4
assert Float64(2.5).rint() == 2

```
## Float64.round

```tomo
Float64.round : func(x: Float64 -> Float64)
```

Rounds a number to the nearest whole number integer.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The number to be rounded.  | -

**Return:** The nearest integer value of `x`.


**Example:**
```tomo
assert Float64(2.3).round() == 2
assert Float64(2.7).round() == 3

```
## Float64.significand

```tomo
Float64.significand : func(x: Float64 -> Float64)
```

Extracts the significand (or mantissa) of a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The number from which to extract the significand.  | -

**Return:** The significand of `x`.


**Example:**
```tomo
assert Float64(1234.567).significand() == 1.2056318359375

```
## Float64.sin

```tomo
Float64.sin : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The angle in radians.  | -

**Return:** The sine of `x`.


**Example:**
```tomo
assert Float64(0.0).sin() == 0

```
## Float64.sinh

```tomo
Float64.sinh : func(x: Float64 -> Float64)
```

Computes the hyperbolic sine of a number.

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

**Return:** The hyperbolic sine of `x`.


**Example:**
```tomo
assert Float64(0.0).sinh() == 0

```
## Float64.sqrt

```tomo
Float64.sqrt : func(x: Float64 -> Float64)
```

Computes the square root of a number.

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

**Return:** The square root of `x`.


**Example:**
```tomo
assert Float64(16.0).sqrt() == 4

```
## Float64.tan

```tomo
Float64.tan : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The angle in radians.  | -

**Return:** The tangent of `x`.


**Example:**
```tomo
assert Float64(0.0).tan() == 0

```
## Float64.tanh

```tomo
Float64.tanh : func(x: Float64 -> Float64)
```

Computes the hyperbolic tangent of a number.

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

**Return:** The hyperbolic tangent of `x`.


**Example:**
```tomo
assert Float64(0.0).tanh() == 0

```
## Float64.tgamma

```tomo
Float64.tgamma : func(x: Float64 -> Float64)
```

Computes the gamma function of a number.

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

**Return:** The gamma function of `x`.


**Example:**
```tomo
assert Float64(1.0).tgamma() == 1

```
## Float64.trunc

```tomo
Float64.trunc : func(x: Float64 -> Float64)
```

Truncates a number to the nearest integer towards zero.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | The number to be truncated.  | -

**Return:** The integer part of `x` towards zero.


**Example:**
```tomo
assert Float64(3.7).trunc() == 3
assert Float64(-3.7).trunc() == -3

```
## Float64.with_precision

```tomo
Float64.with_precision : func(n: Float64, precision: Float64 -> Float64)
```

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

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

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


**Example:**
```tomo
assert Float64(0.1234567).with_precision(0.01) == 0.12
assert Float64(123456.).with_precision(100) == 123500
assert Float64(1234567.).with_precision(5) == 1234565

```
## Float64.y0

```tomo
Float64.y0 : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | 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:**
```tomo
assert Float64(1.0).y0().near(0.08825696421567698)

```
## Float64.y1

```tomo
Float64.y1 : func(x: Float64 -> Float64)
```

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

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Float64` | 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:**
```tomo
assert Float64(1.0).y1().near(-0.7812128213002887)

```

# Int
## Int.abs

```tomo
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:**
```tomo
assert (-10).abs() == 10

```
## Int.choose

```tomo
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:**
```tomo
assert 4.choose(2) == 6

```
## Int.clamped

```tomo
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:**
```tomo
assert 2.clamped(5, 10) == 5

```
## Int.factorial

```tomo
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:**
```tomo
assert 10.factorial() == 3628800

```
## Int.get_bit

```tomo
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:**
```tomo
assert not 6.get_bit(1)
assert 6.get_bit(2)
assert 6.get_bit(3)
assert not 6.get_bit(4)

```
## Int.hex

```tomo
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:**
```tomo
assert 255.hex(digits=4, uppercase=yes, prefix=yes) == "0x00FF"

```
## Int.is_between

```tomo
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:**
```tomo
assert 7.is_between(1, 10)
assert 7.is_between(10, 1)
assert not 7.is_between(100, 200)
assert 7.is_between(1, 7)

```
## Int.is_prime

```tomo
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](https://gmplib.org/manual/Number-Theoretic-Functions#index-mpz_005fprobab_005fprime_005fp) 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:**
```tomo
assert 7.is_prime()
assert not 6.is_prime()

```
## Int.next_prime

```tomo
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](https://gmplib.org/manual/Number-Theoretic-Functions#index-mpz_005fprobab_005fprime_005fp) 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:**
```tomo
assert 11.next_prime() == 13

```
## Int.octal

```tomo
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:**
```tomo
assert 64.octal(digits=4, prefix=yes) == "0o0100"

```
## Int.onward

```tomo
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:**
```tomo
nums : &[Int] = &[]
for i in 5.onward()
    nums.insert(i)
    break if i == 10
assert nums[] == [5, 6, 7, 8, 9, 10]

```
## Int.parse

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert 16.sqrt() == 4
assert 17.sqrt() == 4

```
## Int.to

```tomo
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:**
```tomo
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

```tomo
List.binary_search : func(list: [T], predicate: func(x:T->Bool) -> Int)
```

Performs a binary search on a sorted list.

Argument | Type | Description | Default
---------|------|-------------|---------
list | `[T]` | The sorted list to search.  | -
predicate | `func(x:T->Bool)` | The predicate to look for in the list.  | -

**Return:** Find the first item in the list where the predicate function is true and return its index (or `none` if no such item exists). This assumes that the predicate function is monotonic over the list's contents. In other words, the predicate is false for the first zero or more items in the list and then true for the remainder of the list.


**Example:**
```tomo
# Find an item:
assert [10, 20, 30, 40].binary_search(func(x:Int) x == 30) == 3
# No such item:
assert [10, 20, 30, 40].binary_search(func(x:Int) x == 25) == none
# Find an insertion point (where an item would go to preserve sort order):
assert [10, 20, 30, 40].binary_search(func(x:Int) x >= 25) == 3

```
## List.by

```tomo
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:**
```tomo
assert [1, 2, 3, 4, 5, 6].by(2) == [1, 3, 5]

```
## List.clear

```tomo
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:**
```tomo
list := &[10, 20]
list.clear()
assert list[] == []

```
## List.counts

```tomo
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:**
```tomo
assert [10, 20, 30, 30, 30].counts() == {10:1, 20:1, 30:3}

```
## List.find

```tomo
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:**
```tomo
assert [10, 20, 30, 40, 50].find(20) == 2
assert [10, 20, 30, 40, 50].find(9999) == none

```
## List.from

```tomo
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:**
```tomo
assert [10, 20, 30, 40, 50].from(3) == [30, 40, 50]

```
## List.has

```tomo
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:**
```tomo
assert [10, 20, 30].has(20)

```
## List.heap_pop

```tomo
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:**
```tomo
my_heap := &[30, 10, 20]
my_heap.heapify()
assert my_heap.heap_pop() == 10

```
## List.heap_push

```tomo
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:**
```tomo
my_heap : &[Int]
my_heap.heap_push(10)
assert my_heap.heap_pop() == 10

```
## List.heapify

```tomo
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:**
```tomo
my_heap := &[30, 10, 20]
my_heap.heapify()

```
## List.insert

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
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.pairs

```tomo
List.pairs : func(list: [T] -> func(a:&T, b:&T -> Bool))
```

Returns an iterator that yields each unordered pair of distinct elements exactly once (equivalent to iterating `a` at index `i` and `b` at every later index `j > i`). The iterator yields two values per iteration, so a loop over it binds two variables: `for a, b in list.pairs()`. Mutating the list after making the iterator does not affect what it yields.

Argument | Type | Description | Default
---------|------|-------------|---------
list | `[T]` | The list whose element pairs will be iterated.  | -

**Return:** An iterator function that yields each pair of elements.


**Example:**
```tomo
assert ["$a$b" for a, b in [1, 2, 3].pairs()] == ["12", "13", "23"]

```
## List.pop

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
nums := [10, 20, 30]
pick := nums.random()!
assert nums.has(pick)
empty : [Int]
assert empty.random() == none

```
## List.remove_at

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert [10, 20, 30].reversed() == [30, 20, 10]

```
## List.sample

```tomo
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:**
```tomo
_ := [10, 20, 30].sample(2, weights=[90%, 5%, 5%]) # E.g. [10, 10]

```
## List.shuffle

```tomo
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:**
```tomo
nums := &[10, 20, 30, 40]
nums.shuffle()
# E.g. [20, 40, 10, 30]

```
## List.shuffled

```tomo
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:**
```tomo
nums := [10, 20, 30, 40]
_ := nums.shuffled()
# E.g. [20, 40, 10, 30]

```
## List.slice

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
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.swap

```tomo
List.swap : func(list: @[T], i: Int, j: Int -> Void)
```

Swaps the elements at two indices in place. Compiles inline, so a swap costs one bounds check per index and a single copy-on-write check (a two-element multi-assignment swap pays both twice). Swapping an index with itself is a no-op. Negative indices count from the back of the list, and an out-of-bounds index is a runtime error.

Argument | Type | Description | Default
---------|------|-------------|---------
list | `@[T]` | The mutable reference to the list.  | -
i | `Int` | The index of the first element (1-indexed).  | -
j | `Int` | The index of the second element (1-indexed).  | -

**Return:** Nothing.


**Example:**
```tomo
list := &[10, 20, 30]
list.swap(1, 3)
assert list == [30, 20, 10]

list.swap(2, -1)
assert list == [30, 10, 20]

```
## List.to

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert [10, 20, 10, 10, 30].unique() == {10, 20, 30}

```
## List.where

```tomo
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:**
```tomo
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.PI

```tomo
Num.PI : Num
```

The ratio of a circle's circumference to its diameter, held exactly rather than as an approximation.


**Example:**
```tomo
assert Num.PI.sin() == 0
assert Num.PI.digits(10) == "3.1415926535…"

```
## Num.TAU

```tomo
Num.TAU : Num
```

Two times pi, held exactly.


**Example:**
```tomo
assert Num.TAU == 2 * Num.PI

```
## Num.abs

```tomo
Num.abs : func(x: Num -> Num)
```

The absolute value of a number.

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

**Return:** The absolute value of `x`.


**Example:**
```tomo
assert (-3.5).abs() == 3.5

```
## Num.acos

```tomo
Num.acos : func(x: Num -> Num?)
```

The arc cosine of a number, in radians.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose arc cosine is to be computed.  | -

**Return:** The arc cosine of `x`, or `none` if `x` is outside [-1, 1].


**Example:**
```tomo
assert (1.).acos()! == 0
assert (2.).acos() == none

```
## Num.asin

```tomo
Num.asin : func(x: Num -> Num?)
```

The arc sine of a number, in radians.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose arc sine is to be computed.  | -

**Return:** The arc sine of `x`, or `none` if `x` is outside [-1, 1].


**Example:**
```tomo
assert (0.).asin()! == 0
assert (2.).asin() == none

```
## Num.atan

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

The arc tangent of a number, in radians. Defined for every number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose arc tangent is to be computed.  | -

**Return:** The arc tangent of `x`.


**Example:**
```tomo
assert (0.).atan() == 0
assert (1.).atan() == Num.PI / 4

```
## Num.atan2

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

The angle of the point `(x, y)`, in radians, placed in the correct quadrant by the signs of both arguments.

Argument | Type | Description | Default
---------|------|-------------|---------
y | `Num` | The y coordinate.  | -
x | `Num` | The x coordinate.  | -

**Return:** The angle in (-pi, pi], or `none` at the origin, where no angle is defined.


**Example:**
```tomo
assert (1.).atan2(1)! == Num.PI / 4
assert (0.).atan2(0) == none

```
## Num.ceil

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

The smallest whole number greater than or equal to a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number to round up.  | -

**Return:** `x` rounded up.


**Example:**
```tomo
assert (4.2).ceil() == 5
assert (-4.2).ceil() == -4

```
## Num.clamped

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

A number restricted to a range.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number to clamp.  | -
low | `Num` | The lowest allowed value.  | -
high | `Num` | The highest allowed value.  | -

**Return:** `x`, or the nearer of `low` and `high` if `x` falls outside them.


**Example:**
```tomo
assert (1.5).clamped(0, 1) == 1
assert (0.5).clamped(0, 1) == 0.5

```
## Num.cos

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

The cosine of an angle in radians.

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

**Return:** The cosine of `x`.


**Example:**
```tomo
assert (0.).cos() == 1
assert Num.PI.cos() == -1

```
## Num.cosh

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

The hyperbolic cosine of a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose hyperbolic cosine is to be computed.  | -

**Return:** The hyperbolic cosine of `x`.


**Example:**
```tomo
assert (0.).cosh() == 1

```
## Num.digits

```tomo
Num.digits : func(n: Num, digits: Int = 15, ellipsis: Text = "…" -> Text)
```

The decimal expansion of a number, to at most the requested number of fractional digits. A value that fits exactly stops early rather than padding with zeros, and gets no marker. A value that doesn't shows a truncated prefix of its true expansion with the ellipsis appended, and never a rounding: every digit shown is a digit the value actually has. To round, round first.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to expand.  | -
digits | `Int` | The maximum number of fractional digits.  | `15`
ellipsis | `Text` | Appended when the digits don't capture the value exactly.  | `"…"`

**Return:** The decimal expansion as text.


**Example:**
```tomo
assert (1/3).digits(10) == "0.3333333333…"
assert Num.PI.digits(10) == "3.1415926535…"
assert (2/3).digits(10, ellipsis="") == "0.6666666666"
assert (0.25).digits(10) == "0.25"

```
## Num.exp

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

e raised to the given power.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The exponent.  | -

**Return:** e to the power of `x`.


**Example:**
```tomo
assert (0.).exp() == 1

```
## Num.floor

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

The largest whole number less than or equal to a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number to round down.  | -

**Return:** `x` rounded down.


**Example:**
```tomo
assert (4.8).floor() == 4
assert (-4.2).floor() == -5

```
## Num.gcd

```tomo
Num.gcd : func(x: Num, y: Num -> Num?)
```

The greatest common divisor of two numbers, generalized to fractions: the largest value by which both can be divided to give whole numbers.

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

**Return:** The greatest common divisor, or `none` if either argument is irrational and so has no such divisor.


**Example:**
```tomo
assert (12.).gcd(18)! == 6
assert (1./2.).gcd(1./3.)! == 1./6.

```
## Num.inverse

```tomo
Num.inverse : func(x: Num -> Num?)
```

One divided by a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number to invert.  | -

**Return:** The reciprocal of `x`, or `none` if `x` is zero.


**Example:**
```tomo
assert (4.).inverse()! == 0.25
assert (0.).inverse() == none

```
## Num.is_between

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

Whether a number lies within a range, inclusive.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number to check.  | -
low | `Num` | The lower bound.  | -
high | `Num` | The upper bound.  | -

**Return:** `yes` if `low <= x <= high`.


**Example:**
```tomo
assert (0.5).is_between(0, 1)
assert not (1.5).is_between(0, 1)

```
## Num.is_exact

```tomo
Num.is_exact : func(n: Num, digits: Int = 15 -> Bool)
```

Whether the requested number of fractional digits represents a number exactly, rather than rounding it.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to check.  | -
digits | `Int` | The number of fractional digits.  | `15`

**Return:** `yes` if `:digits(digits)` is the value itself.


**Example:**
```tomo
assert (0.25).is_exact(10)
assert not (1./3.).is_exact(10)

```
## Num.is_integer

```tomo
Num.is_integer : func(n: Num -> Bool)
```

Whether a number is a whole number.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to check.  | -

**Return:** `yes` if `n` has no fractional part.


**Example:**
```tomo
assert (4.).is_integer()
assert not (4.5).is_integer()

```
## Num.is_rational

```tomo
Num.is_rational : func(n: Num -> Bool)
```

Whether a number can be written exactly as a fraction, as opposed to an irrational value like the square root of two.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to check.  | -

**Return:** `yes` if `n` is rational.


**Example:**
```tomo
assert (1./3.).is_rational()
assert not (2.).sqrt()!.is_rational()

```
## Num.lcm

```tomo
Num.lcm : func(x: Num, y: Num -> Num?)
```

The least common multiple of two numbers, generalized to fractions.

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

**Return:** The least common multiple, or `none` if either argument is irrational.


**Example:**
```tomo
assert (4.).lcm(6)! == 12

```
## Num.log

```tomo
Num.log : func(x: Num -> Num?)
```

The natural logarithm of a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose logarithm is to be computed.  | -

**Return:** The natural log of `x`, or `none` if `x` is not positive.


**Example:**
```tomo
assert (1.).log()! == 0
assert (0.).log() == none

```
## Num.log10

```tomo
Num.log10 : func(x: Num -> Num?)
```

The base-10 logarithm of a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose logarithm is to be computed.  | -

**Return:** The base-10 log of `x`, or `none` if `x` is not positive.


**Example:**
```tomo
assert (100.).log10()! == 2

```
## Num.log2

```tomo
Num.log2 : func(x: Num -> Num?)
```

The base-2 logarithm of a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose logarithm is to be computed.  | -

**Return:** The base-2 log of `x`, or `none` if `x` is not positive.


**Example:**
```tomo
assert (8.).log2()! == 3
assert (1./4.).log2()! == -2

```
## Num.max

```tomo
Num.max : func(x: Num, y: Num -> Num)
```

The larger of two numbers.

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

**Return:** Whichever of `x` and `y` is larger.


**Example:**
```tomo
assert (0.3).max(0.5) == 0.5

```
## Num.min

```tomo
Num.min : func(x: Num, y: Num -> Num)
```

The smaller of two numbers.

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

**Return:** Whichever of `x` and `y` is smaller.


**Example:**
```tomo
assert (0.3).min(0.5) == 0.3

```
## Num.mix

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

A point between two numbers, exactly. `amount` of zero gives `x`, one gives `y`, and a half gives the true midpoint.

Argument | Type | Description | Default
---------|------|-------------|---------
amount | `Num` | How far from `x` toward `y`.  | -
x | `Num` | The value at `amount` zero.  | -
y | `Num` | The value at `amount` one.  | -

**Return:** The interpolated value.


**Example:**
```tomo
assert (0.25).mix(10, 20) == 12.5
assert (1./3.).mix(0, 1) == 1./3.

```
## Num.parse

```tomo
Num.parse : func(text: Text -> Num?)
```

The exact number a piece of text denotes. Both decimals and fractions are accepted, and both are read exactly: "0.1" is a tenth, not the nearest float to one.

Argument | Type | Description | Default
---------|------|-------------|---------
text | `Text` | The text to parse.  | -

**Return:** The number, or `none` if the text isn't one.


**Example:**
```tomo
assert Num.parse("0.1")! == 0.1
assert Num.parse("22/7")! == 22./7.
assert Num.parse("nope") == none

```
## Num.percent

```tomo
Num.percent : func(n: Num, precision: Num = 1% -> Text)
```

A number as a percentage, rounded to the given precision.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to format.  | -
precision | `Num` | Round the percentage to this precision.  | `1%`

**Return:** The percentage, with a percent sign.


**Example:**
```tomo
assert (0.5).percent() == "50%"
assert (1./3.).percent() == "33%"
assert (1./3.).percent(0.01%) == "33.33%"

```
## Num.round

```tomo
Num.round : func(x: Num, increment: Num = 1 -> Num)
```

The nearest multiple of an increment, exactly: the nearest penny, nickel, third, or thousand are all one argument away, and the default increment of 1 gives the nearest whole number. Ties go to the even multiple.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number to round.  | -
increment | `Num` | The step to round to a multiple of. Rounding to zero is an error.  | `1`

**Return:** `x` rounded to the nearest multiple of `increment`.


**Example:**
```tomo
assert (4.6).round() == 5
assert (2.5).round() == 2
assert (3.14159).round(0.01) == 3.14
assert (0.13).round(0.05) == 0.15
assert (0.5).round(1/3) == 2/3
assert (1234567.).round(1000) == 1235000

```
## Num.sin

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

The sine of an angle in radians.

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

**Return:** The sine of `x`.


**Example:**
```tomo
assert (0.).sin() == 0
assert Num.PI.sin() == 0

```
## Num.sinh

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

The hyperbolic sine of a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose hyperbolic sine is to be computed.  | -

**Return:** The hyperbolic sine of `x`.


**Example:**
```tomo
assert (0.).sinh() == 0

```
## Num.sqrt

```tomo
Num.sqrt : func(x: Num -> Num?)
```

The square root of a number, exactly. The result of a non-square stays symbolic, so identities like `sqrt(2) * sqrt(2) == 2` hold.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose square root is to be computed.  | -

**Return:** The square root of `x`, or `none` if `x` is negative.


**Example:**
```tomo
assert (16.).sqrt()! == 4
assert (2.).sqrt()! * (2.).sqrt()! == 2
assert (-1.).sqrt() == none

```
## Num.symbolic

```tomo
Num.symbolic : func(n: Num -> Text)
```

The exact value written out: a whole number, a fraction, or a symbolic expression for an irrational.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to write out.  | -

**Return:** The exact form.


**Example:**
```tomo
assert (1./3.).symbolic() == "1/3"
assert (2.).sqrt()!.symbolic() == "sqrt(2)"
assert Num.PI.symbolic() == "pi"

```
## Num.tan

```tomo
Num.tan : func(x: Num -> Num?)
```

The tangent of an angle in radians.

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

**Return:** The tangent of `x`, or `none` at a pole.


**Example:**
```tomo
assert (0.).tan()! == 0

```
## Num.tanh

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

The hyperbolic tangent of a number.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number whose hyperbolic tangent is to be computed.  | -

**Return:** The hyperbolic tangent of `x`.


**Example:**
```tomo
assert (0.).tanh() == 0

```
## Num.tex

```tomo
Num.tex : func(n: Num -> Text)
```

The exact value as TeX math-mode source.

Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to render.  | -

**Return:** The TeX source.


**Example:**
```tomo
assert (1./3.).tex() == "\\frac{1}{3}"
assert (2.).sqrt()!.tex() == "\\sqrt{2}"

```
## Num.trunc

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

The whole part of a number, discarding the fraction.

Argument | Type | Description | Default
---------|------|-------------|---------
x | `Num` | The number to truncate.  | -

**Return:** `x` with its fractional part removed.


**Example:**
```tomo
assert (4.8).trunc() == 4
assert (-4.8).trunc() == -4

```

# Path
## Path.accessed

```tomo
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:**
```tomo
assert (./file.txt).accessed() == Int64(1704221100)
assert (./not-a-file).accessed() == none

```
## Path.append

```tomo
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:**
```tomo
(./log.txt).append("extra line\n")!

```
## Path.append_bytes

```tomo
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:**
```tomo
(./log.txt).append_bytes([104, 105])!

```
## Path.base_name

```tomo
Path.base_name : func(path: Path -> Text?)
```

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

A POSIX filename is an arbitrary sequence of bytes, but `Text` holds Unicode, so this returns `none` when the name is not valid UTF-8.

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

**Return:** The base name of the file or directory, or `none` if it is not valid UTF-8.


**Example:**
```tomo
assert (./path/to/file.txt).base_name() == "file.txt"

```
## Path.by_line

```tomo
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:**
```tomo
# 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

```tomo
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:**
```tomo
write := (./file.txt).byte_writer()
write("Hello\n".utf8())!
write("world\n".utf8(), close=yes)!

```
## Path.bytes

```tomo
Path.bytes : func(path: Path -> [Byte])
```

Convert a path to a list of the raw bytes that make up its text representation. This does not read the file at the given path; see `Path.read_bytes` for that.

Argument | Type | Description | Default
---------|------|-------------|---------
path | `Path` | The path.  | -

**Return:** A list of bytes (`[Byte]`) representing the path's text.


**Example:**
```tomo
assert (/foo/bar).bytes() == [47, 102, 111, 111, 47, 98, 97, 114]

```
## Path.can_execute

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

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

This answers about the moment it is asked, and another process can change it immediately after. Do not use it to decide whether an operation will succeed: attempt the operation and handle its `Failure` instead.

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:**
```tomo
assert (/bin/sh).can_execute()
assert not (/usr/include/stdlib.h).can_execute()
assert not (/non/existant/file).can_execute()

```
## Path.can_read

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

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

This answers about the moment it is asked, and another process can change it immediately after. Do not use it to decide whether an operation will succeed: attempt the operation and handle its `Failure` instead.

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:**
```tomo
assert (/usr/include/stdlib.h).can_read()
assert not (/etc/shadow).can_read()
assert not (/non/existant/file).can_read()

```
## Path.can_write

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

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

This answers about the moment it is asked, and another process can change it immediately after. Do not use it to decide whether an operation will succeed: attempt the operation and handle its `Failure` instead.

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:**
```tomo
assert (/tmp).can_write()
assert not (/etc/passwd).can_write()
assert not (/non/existant/file).can_write()

```
## Path.changed

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

Gets the file change time of a file.

This is the ["ctime"](https://en.wikipedia.org/wiki/Stat_(system_call)#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:**
```tomo
assert (./file.txt).changed() == Int64(1704221100)
assert (./not-a-file).changed() == none

```
## Path.child

```tomo
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:**
```tomo
assert (./directory).child("file.txt") == (./directory/file.txt)

```
## Path.children

```tomo
Path.children : func(path: Path, include_hidden: Bool = 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.

The paths returned keep the form of the path they came from: the children of `(./foo)` are relative and the children of `(~/foo)` stay home-based. Use `.resolved()` on them if you need absolute paths.

Returns `none` if the path is not a readable directory.

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 paths for the children, or `none` if the directory could not be read. An existing but empty directory gives an empty list, not `none`.


**Example:**
```tomo
assert (./directory).children(include_hidden=yes)!.sorted() == [(./directory/.git), (./directory/foo.txt)]

# A directory that can't be read gives `none`, not an empty list:
assert (./not-a-directory).children() == none

```
## Path.components

```tomo
Path.components : func(path: Path -> [Text]?)
```

Returns a list of the file components of a path.

A POSIX filename is an arbitrary sequence of bytes, but `Text` holds Unicode, so this returns `none` when the name is not valid UTF-8.

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

**Return:** Each of the file components of the path in a list, or `none` if any component is not valid UTF-8. Note: for absolute paths, the first component will be "/". Trailing slashes are ignored.


**Example:**
```tomo
assert (./foo/baz.txt).components() == [".", "foo", "baz.txt"]
assert (/absolute/path/).components() == ["/", "absolute", "path"]

```
## Path.concatenated_with

```tomo
Path.concatenated_with : func(a: Path, b: Path -> Path)
```

Return the concatenation of two paths. This is what the `++` operator does on paths. The result is normalized, so `.` and `..` components in the second path are resolved away.

Argument | Type | Description | Default
---------|------|-------------|---------
a | `Path` | The base path.  | -
b | `Path` | A relative path to append. It is a runtime error if this is an absolute or home-based path.  | -

**Return:** The second path appended to the first.


**Example:**
```tomo
assert (/foo/bar).concatenated_with((./baz)) == (/foo/bar/baz)
assert ((/foo/bar) ++ (./baz/../qux)) == (/foo/bar/qux)

```
## Path.copy_to

```tomo
Path.copy_to : func(path: Path, dest: Path, overwrite: Bool = no -> Result)
```

Copies the file or directory from one location to another. This is the same behavior as `cp -rn -T src dest` or `cp -rf -T src dest` (if `overwrite` is enabled).

Copying a tree is many operations rather than one, so unlike `Path.move` this cannot be indivisible. With `overwrite=no` an existing destination is never written over, but if one appears while the copy is running it is skipped silently rather than reported.

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

**Return:** Either `Success` or `Failure{reason}`.


**Example:**
```tomo
(./file.txt).copy_to(/tmp/copy.txt)!

```
## Path.create_directory

```tomo
Path.create_directory : func(path: Path, permissions: Int32 = Int32(0o755), recursive: Bool = 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.

A directory that already exists is a success, which is what makes this safe to call when another process may be creating the same directory. Something that exists but is not a directory is a failure.

Argument | Type | Description | Default
---------|------|-------------|---------
path | `Path` | The path of the directory to create.  | -
permissions | `Int32` | The permissions to set on the new directory.  | `Int32(0o755)`
recursive | `Bool` | 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:**
```tomo
(./new_directory).create_directory()!

```
## Path.current_dir

```tomo
Path.current_dir : func(-> Path)
```

Returns the absolute path of the current working directory.


**Return:** The absolute path of the current directory.


**Example:**
```tomo
assert Path.current_dir() == (/home/user/tomo)

```
## Path.each_child

```tomo
Path.each_child : func(path: Path, include_hidden: Bool = 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.

The paths returned keep the form of the path they came from: the children of `(./foo)` are relative and the children of `(~/foo)` stay home-based. Use `.resolved()` on them if you need absolute paths.

Returns `none` if the path is not a readable directory.

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:** An iterator over the children in a directory, or `none` if the directory could not be read.


**Example:**
```tomo
# Safely handle the directory not being readable:
if children := (/dir).each_child()
    for child in children
        say("Child: $child")
else
    say("Couldn't read the directory!")

# Assume the directory is readable and error if that's not the case:
for child in (/dir).each_child()!
    say("Child: $child")

```
## Path.exists

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

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

This answers about the moment it is asked. Deciding what to do from it races with anything else touching the filesystem; prefer operations that say what they did, such as `Path.create_directory` (which succeeds if the directory is already there) or `Path.remove` with `ignore_missing`.

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

**Return:** `yes` if the file or directory exists, otherwise `no`.


**Example:**
```tomo
assert (/).exists()

```
## Path.expand_home

```tomo
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:**
```tomo
# Assume current user is 'user'
assert (~/foo).expand_home() == (/home/user/foo)
# No change
assert (/foo).expand_home() == (/foo)

```
## Path.extension

```tomo
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.

A name with no `.` in it has no extension, and gives `none` rather than an empty text. A leading `.` does not count, so a dotfile like `(./.git)` has no extension, and neither does a name ending in a `.`.

Also returns `none` when the name is not valid UTF-8, a POSIX filename being an arbitrary sequence of bytes while `Text` holds Unicode.

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 `none` if there is no extension.


**Example:**
```tomo
assert (./file.tar.gz).extension() == "tar.gz"
assert (./file.tar.gz).extension(full=no) == "gz"

# No "." in the name means no extension:
assert (/foo).extension() == none
assert (./.git).extension() == none
assert (./foo.).extension() == none

```
## Path.files

```tomo
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.

The paths returned keep the form of the path they came from: the children of `(./foo)` are relative and the children of `(~/foo)` stay home-based. Use `.resolved()` on them if you need absolute paths.

Returns `none` if the path is not a readable directory.

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, or `none` if the directory could not be read. A directory with no files in it gives an empty list, not `none`.


**Example:**
```tomo
assert (./directory).files(include_hidden=yes)!.sorted() == [(./directory/file1.txt), (./directory/file2.txt)]

```
## Path.glob

```tomo
Path.glob : func(path: Path, pattern: Text -> [Path]?)
```

Search a directory for paths matching a glob pattern. The pattern is relative to the directory, and unlike `Path.matches_glob` it is anchored: it has to account for every component below the directory.

Details of the pattern syntax:
- `?`, `*`, and character classes like `[ch]` match within a single
  component and never across a `/`.

- Files or directories beginning with `.` will not match `*`, but will
  match `.*`. The paths "." and ".." are never included in the results.

- `**` stands for zero or more components, so `"**/*.txt"` finds `.txt`
  files at any depth. Unlike the other syntax, this cannot be answered by
  `glob(3)`, so such a pattern is served by walking the directory tree.
  `**` spans hidden components too, which is what makes it agree with
  `Path.matches_glob`. It does *not* descend through a symbolic link to a
  directory, since a link pointing back at an ancestor would never
  terminate; an explicit `*` component still matches one, so
  `"*/x.txt"` can find a file that `"**/x.txt"` will not.

- The `{a,b}` alternation syntax is not supported.
Results keep the form of the directory they came from, so globbing `(./src)` yields relative paths and globbing `(~/src)` yields home-based ones. Every path returned satisfies `Path.matches_glob` for the same pattern.

Returns `none` if the directory could not be read. A pattern that simply matches nothing gives an empty list, not `none`.

Argument | Type | Description | Default
---------|------|-------------|---------
path | `Path` | The directory to search.  | -
pattern | `Text` | The glob pattern to match against, relative to the directory. An empty pattern matches nothing.  | -

**Return:** A sorted list of the paths that match, or `none` if the directory could not be read.


**Example:**
```tomo
# A directory containing: foo.txt, baz.txt, qux.jpg, .hidden, sub/deep.txt
assert (./dir).glob("*.txt")! == [(./dir/baz.txt), (./dir/foo.txt)]
assert (./dir).glob(".*")! == [(./dir/.hidden)]
assert (./dir).glob("sub/*.txt")! == [(./dir/sub/deep.txt)]

# "**" is zero or more components:
assert (./dir).glob("**/*.txt")! == [(./dir/baz.txt), (./dir/foo.txt), (./dir/sub/deep.txt)]

# A pattern matching nothing is an empty list:
assert (./dir).glob("*.xxx")! == []

# A directory that can't be read is none:
assert (./not-a-directory).glob("*") == none

```
## Path.group

```tomo
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:**
```tomo
assert (/bin).group() == "root"
assert (/non/existent/file).group() == none

```
## Path.has_extension

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

Return whether or not a path has a given file extension. Unlike `Path.extension`, this reads the raw bytes of the name and so works on names that are not valid UTF-8.

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:**
```tomo
assert (/foo.txt).has_extension("txt")
assert (/foo.txt).has_extension(".txt")
assert (/foo.tar.gz).has_extension("gz")
assert not (/foo.tar.gz).has_extension("zip")

# Asking for an empty extension is the same question as `.extension()`
# being `none`, for any name that is valid UTF-8:
assert (/foo).has_extension("")
assert (/).has_extension("")

```
## Path.is_directory

```tomo
Path.is_directory : func(path: Path, follow_symlinks: Bool = 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 | `Bool` | Whether to follow symbolic links.  | `yes`

**Return:** `yes` if the path is a directory, otherwise `no`.


**Example:**
```tomo
assert (./directory/).is_directory()
assert not (./file.txt).is_directory()

```
## Path.is_file

```tomo
Path.is_file : func(path: Path, follow_symlinks: Bool = 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 | `Bool` | Whether to follow symbolic links.  | `yes`

**Return:** `yes` if the path is a file, otherwise `no`.


**Example:**
```tomo
assert (./file.txt).is_file()
assert not (./directory/).is_file()

```
## Path.is_pipe

```tomo
Path.is_pipe : func(path: Path, follow_symlinks: Bool = yes -> Bool)
```

Checks if the path represents a named pipe (a FIFO). Optionally follows symbolic links.

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

**Return:** `yes` if the path is a named pipe, otherwise `no`.


**Example:**
```tomo
assert (./my-fifo).is_pipe()
assert not (./file.txt).is_pipe()

```
## Path.is_socket

```tomo
Path.is_socket : func(path: Path, follow_symlinks: Bool = 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 | `Bool` | Whether to follow symbolic links.  | `yes`

**Return:** `yes` if the path is a socket, otherwise `no`.


**Example:**
```tomo
assert (./socket).is_socket()

```
## Path.is_symlink

```tomo
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:** `yes` if the path is a symbolic link, otherwise `no`.


**Example:**
```tomo
assert (./link).is_symlink()

```
## Path.lines

```tomo
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:**
```tomo
lines := (./file.txt).lines()!

```
## Path.matches_glob

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

Return whether or not a path matches a given glob. This is a pattern match, not a filesystem operation, and it reads the raw bytes of the path, so it works on names that are not valid UTF-8.

The pattern is split on `/` and matched against the path's components from the back, so a pattern matches any trailing run of components:
- `"*.txt"` asks about the file's name wherever it sits, so it matches
  `(./foo.txt)`, `(/tmp/dir/foo.txt)`, and `(~/foo.txt)` alike. The answer
  does not depend on which form the path was written in.

- `"dir/*.txt"` matches a `.txt` file directly inside any `dir`.
- A pattern beginning with `/` can only line up at the front of the path,
  so `"/tmp/*.txt"` pins the whole path rather than matching a suffix. A
  pattern beginning with `./` likewise only matches `./`-form paths.

- `**` stands for zero or more components, so `"**/*.txt"` matches a `.txt`
  file at any depth, including none.

- `?`, `*`, and character classes like `[ch]` match within a single
  component and never across a `/`. A `.` at the start of a component must
  be matched by a literal `.`, so `*` does not match hidden files.

- The `{a,b}` alternation syntax is not supported.

An empty pattern matches nothing.

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:**
```tomo
# A bare pattern asks about the file's name, whatever form the path is in:
assert (./file.txt).matches_glob("*.txt")
assert (/tmp/dir/file.txt).matches_glob("*.txt")
assert not (./file.txt).matches_glob("*.jpg")

# More components match a longer suffix:
assert (./src/file.c).matches_glob("src/*.[ch]")
assert (./src/file.c).matches_glob("./src/*.[ch]")

# A leading "/" anchors the pattern to the whole path:
assert (/tmp/dir/file.txt).matches_glob("/tmp/dir/*.txt")
assert not (/other/dir/file.txt).matches_glob("/tmp/dir/*.txt")

# "**" is zero or more components:
assert (./a/b/c/file.txt).matches_glob("**/*.txt")
assert (./file.txt).matches_glob("**/*.txt")

# "*" does not match a leading "." or cross a "/":
assert not (./dir/.hidden).matches_glob("*")
assert (./dir/.hidden).matches_glob(".*")

```
## Path.modified

```tomo
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:**
```tomo
assert (./file.txt).modified() == Int64(1704221100)
assert (./not-a-file).modified() == none

```
## Path.move

```tomo
Path.move : func(path: Path, dest: Path, overwrite: Bool = no -> Result)
```

Moves the file or directory from one location to another.

With `overwrite=no`, the refusal and the move are a single operation the kernel performs indivisibly, so another process cannot slip a file into the destination in between. Moving a directory across filesystems is the one case that cannot be done that way and falls back to checking first.

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

**Return:** Either `Success` or `Failure{reason}`.


**Example:**
```tomo
(./file.txt).move(/tmp/renamed.txt)!

```
## Path.owner

```tomo
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:**
```tomo
assert (/bin).owner() == "root"
assert (/non/existent/file).owner() == none

```
## Path.parent

```tomo
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:**
```tomo
assert (./path/to/file.txt).parent() == (./path/to)

```
## Path.read

```tomo
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:**
```tomo
assert (./hello.txt).read() == "Hello"
assert (./nosuchfile.xxx).read() == none

```
## Path.read_bytes

```tomo
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:**
```tomo
assert (./hello.txt).read_bytes()! == [72, 101, 108, 108, 111]
assert (./nosuchfile.xxx).read_bytes() == none

```
## Path.relative_to

```tomo
Path.relative_to : func(path: Path, relative_to: Path -> Path)
```

Returns the path relative to a given base path.

The result has no leading `./`, so a path naming something inside the base path cannot be written as a path literal. Results that climb out of the base path begin with `../` and can.

Argument | Type | Description | Default
---------|------|-------------|---------
path | `Path` | The path to convert.  | -
relative_to | `Path` | The base path for the relative path. Unlike `Path.resolved`, this argument is required.  | -

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


**Example:**
```tomo
# A path relative to itself is the current directory:
assert (/tmp).relative_to((/tmp)) == (.)
assert "$((./path/to/file.txt).relative_to((./path)))" == "to/file.txt"
assert "$((/tmp/foo).relative_to((/tmp)))" == "foo"
assert (/a/b/c).relative_to((/a/x)) == (../b/c)

```
## Path.remove

```tomo
Path.remove : func(path: Path, ignore_missing: Bool = 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 | `Bool` | Whether to ignore errors if the file or directory does not exist.  | `no`

**Return:** Either `Success` or `Failure{reason}`.


**Example:**
```tomo
(./file.txt).remove()!

```
## Path.resolved

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

Resolves the absolute path of the given path relative to a base path. By default, the base path is the current directory. A relative base is itself resolved against the current directory first, so the result is always absolute.

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

**Return:** The resolved absolute path.


**Example:**
```tomo
# Assume the current directory is /home/user
assert (~/foo).resolved() == (/home/user/foo)
assert (./foo).resolved() == (/home/user/foo)
assert (./path/to/file.txt).resolved(relative_to=(/foo)) == (/foo/path/to/file.txt)

```
## Path.set_owner

```tomo
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:**
```tomo
(./file.txt).set_owner(owner="root", group="wheel")!

```
## Path.sibling

```tomo
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)`

Returns `none` for a path with no parent to put a sibling beside, which is the file root `(/)`.

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, or `none` if the path is `(/)`.


**Example:**
```tomo
assert (/foo/baz).sibling("doop") == (/foo/doop)
assert (/).sibling("doop") == none

```
## Path.subdirectories

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

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

The paths returned keep the form of the path they came from: the children of `(./foo)` are relative and the children of `(~/foo)` stay home-based. Use `.resolved()` on them if you need absolute paths.

Returns `none` if the path is not a readable directory.

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

**Return:** A list of subdirectory paths, or `none` if the directory could not be read. A directory with no subdirectories gives an empty list, not `none`.


**Example:**
```tomo
assert (./directory).subdirectories()!.sorted() == [(./directory/subdir1), (./directory/subdir2)]
assert (./directory).subdirectories(include_hidden=yes)!.sorted() == [(./directory/.git), (./directory/subdir1), (./directory/subdir2)]

```
## Path.unique_directory

```tomo
Path.unique_directory : func(path: Path -> Path?)
```

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

Returns `none` if the directory could not be created.

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, or `none` if it could not be created.


**Example:**
```tomo
created := (/tmp/my-dir.XXXXXX).unique_directory()!
assert created.is_directory()
created.remove()!

```
## Path.walk

```tomo
Path.walk : func(path: Path, include_hidden: Bool = 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. The paths returned keep the form of the path they came from: walking `(./foo)` yields relative paths and walking `(~/foo)` yields home-based ones.

Returns `none` if there is nothing at the given path. A path that exists but is not a directory walks over just itself.

Argument | Type | Description | Default
---------|------|-------------|---------
path | `Path` | The path to begin the walk.  | -
include_hidden | `Bool` | 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, or `none` if the path does not exist.


**Example:**
```tomo
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)]

# A path that isn't there has nothing to walk:
assert (./not-a-path).walk() == none

```
## Path.with_extension

```tomo
Path.with_extension : func(path: Path, extension: Text, replace: Bool = yes -> Path)
```

Return a path with the given file extension, either replacing the path's existing extension or adding to it.

Argument | Type | Description | Default
---------|------|-------------|---------
path | `Path` | A path.  | -
extension | `Text` | The file extension to apply (a leading `.` is optional). If empty, the extension is removed entirely.  | -
replace | `Bool` | If `yes`, the path's existing extension is replaced. If `no`, the new extension is appended to the existing one.  | `yes`

**Return:** A new path with the requested extension.


**Example:**
```tomo
assert (./file.tar.gz).with_extension("zip") == (./file.zip)
assert (./file.tar.gz).with_extension(".zip") == (./file.zip)
assert (./file.tar.gz).with_extension("") == (./file)
assert (./file.tar.gz).with_extension("zip", replace=no) == (./file.tar.gz.zip)
assert (./file).with_extension("txt") == (./file.txt)

```
## Path.write

```tomo
Path.write : func(path: Path, text: Text, permissions: Int32 = 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 | `Int32` | The permissions to set on the file if it is created.  | `Int32(0o644)`

**Return:** Either `Success` or `Failure{reason}`.


**Example:**
```tomo
(./file.txt).write("Hello, world!")!

```
## Path.write_bytes

```tomo
Path.write_bytes : func(path: Path, bytes: [Byte], permissions: Int32 = 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 | `Int32` | The permissions to set on the file if it is created.  | `Int32(0o644)`

**Return:** Either `Success` or `Failure{reason}`.


**Example:**
```tomo
(./file.txt).write_bytes([104, 105])!

```
## Path.write_unique

```tomo
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, or `none` if the file could not be created.


**Example:**
```tomo
# The created path has the XXXXXX replaced by random characters,
# e.g. (./file-27QHtq.txt):
created := (./file-XXXXXX.txt).write_unique("Hello, world!")!
assert created.read()! == "Hello, world!"
created.remove()!

```
## Path.write_unique_bytes

```tomo
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, or `none` if the file could not be created.


**Example:**
```tomo
# The created path has the XXXXXX replaced by random characters,
# e.g. (./file-27QHtq.txt):
created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!
assert created.read_bytes()! == [1, 2, 3]
created.remove()!

```
## Path.writer

```tomo
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:**
```tomo
write := (./file.txt).writer()
write("Hello\n")!
write("world\n", close=yes)!

```

# Table
## Table.clear

```tomo
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:**
```tomo
t := &{"A":1}
t.clear()
assert t[] == {}

```
## Table.difference

```tomo
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:**
```tomo
t1 := {"A": 1, "B": 2, "C": 3}
t2 := {"B": 2, "C":30, "D": 40}
assert t1.difference(t2) == {"A": 1, "D": 40}

```
## Table.entries

```tomo
Table.entries : func(t: {K:V} -> func(key:&K, value:&V -> Bool))
```

Returns an iterator that yields each key/value pair in the table, in insertion order. The iterator yields two values per iteration, so a loop over it binds two variables: `for k, v in table.entries()`. This is the only way to iterate a table's pairs (`for k, v in table` is a compile error); use the `.keys` or `.values` fields to iterate just one side. Mutating the table after making the iterator does not affect what it yields.

Argument | Type | Description | Default
---------|------|-------------|---------
t | `{K:V}` | The table whose entries will be iterated.  | -

**Return:** An iterator function that yields each key/value pair.


**Example:**
```tomo
t := {"A": 1, "B": 2}
assert ["$k=$v" for k, v in t.entries()] == ["A=1", "B=2"]

```
## Table.get

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert {"A": 1, "B": 2}.has("A")
assert not {"A": 1, "B": 2}.has("xxx")

```
## Table.intersection

```tomo
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:**
```tomo
t1 := {"A": 1, "B": 2, "C": 3}
t2 := {"B": 2, "C":30, "D": 40}
assert t1.intersection(t2) == {"B": 2}

```
## Table.remove

```tomo
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:**
```tomo
t := &{"A": 1, "B": 2}
t.remove("A")
assert t == {"B": 2}

```
## Table.set

```tomo
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:**
```tomo
t := &{"A": 1, "B": 2}
t.set("C", 3)
assert t == {"A": 1, "B": 2, "C": 3}

```
## Table.with

```tomo
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:**
```tomo
t := {"A": 1, "B": 2}
assert t.with({"B": 20, "C": 30}) == {"A": 1, "B": 20, "C": 30}

```
## Table.with_fallback

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert "Hello".as_c_string() == CString("Hello")

```
## Text.at

```tomo
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.

Returns `none` if the index is out of range. This is unlike `text[i]`, which fails with an error instead of giving back a value.

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, or `none` if there is no cluster there.


**Example:**
```tomo
assert "Amélie".at(3) == "é"
assert "Amélie".at(-1) == "e"
assert "Amélie".at(99) == none

```
## Text.by_line

```tomo
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:**
```tomo
text := "
    line one
    line two
"
lines := [line for line in text.by_line()]
assert lines == ["line one", "line two"]

```
## Text.by_split

```tomo
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:**
```tomo
text := "one,two,three"
chunks := [chunk for chunk in text.by_split(",")]
assert chunks == ["one", "two", "three"]

```
## Text.by_split_any

```tomo
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:**
```tomo
text := "one,two,;,three"
chunks := [chunk for chunk in text.by_split_any(",;")]
assert chunks == ["one", "two", "three"]

```
## Text.caseless_equals

```tomo
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:**
```tomo
assert "A".caseless_equals("a")

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

```
## Text.codepoint_names

```tomo
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:**
```tomo
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

```tomo
Text.distance : func(a: Text, b: Text -> 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.  | -

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


**Example:**
```tomo
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"]
assert "kitten".distance("sitting") == 3
assert "flaw".distance("lawn") == 2
# A transposition costs one edit, even when the texts differ in length:
assert "ab".distance("ba") == 1
assert "xab".distance("ba") == 2

```
## Text.ends_with

```tomo
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:**
```tomo
assert "hello world".ends_with("world")
remainder : Text
assert "hello world".ends_with("world", &remainder)
assert remainder == "hello "

```
## Text.find

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert "hello".from(2) == "ello"
assert "hello".from(-2) == "lo"

```
## Text.from_c_string

```tomo
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:**
```tomo
assert Text.from_c_string(CString("Hello")) == "Hello"

```
## Text.from_codepoint_names

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert Text.from_utf16([197, 107, 101]) == "Åke"
assert Text.from_utf16([12371, 12435, 12395, 12385, 12399, 19990, 30028]) == "こんにちは世界"

```
## Text.from_utf32

```tomo
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:**
```tomo
assert Text.from_utf32([197, 107, 101]) == "Åke"

```
## Text.from_utf8

```tomo
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:**
```tomo
assert Text.from_utf8([195, 133, 107, 101]) == "Åke"

```
## Text.has

```tomo
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:**
```tomo
assert "hello world".has("wo")
assert not "hello world".has("xxx")

```
## Text.join

```tomo
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:**
```tomo
assert ", ".join(["one", "two", "three"]) == "one, two, three"

```
## Text.left_pad

```tomo
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:**
```tomo
assert "x".left_pad(5) == "    x"
assert "x".left_pad(5, "ABC") == "ABCAx"

```
## Text.lines

```tomo
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:**
```tomo
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

```tomo
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:**
```tomo
assert "AMÉLIE".lower() == "amélie"
assert "I".lower(language="tr_TR") == "ı"

```
## Text.matches_glob

```tomo
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:**
```tomo
assert "hello world".matches_glob("h* *d")

```
## Text.middle_pad

```tomo
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:**
```tomo
assert "x".middle_pad(6) == "  x   "
assert "x".middle_pad(10, "ABC") == "ABCAxABCAB"

```
## Text.nearest

```tomo
Text.nearest : func(text: Text, candidates: [Text], max_distance: Num = 0.6 -> Text?)
```

Find which of `candidates` is most similar to this text, for suggesting a correction when a name isn't recognized. Similarity uses `Text.distance()`, and candidates that aren't close enough are ignored.

`max_distance` is an edit distance *per grapheme*, measured against the shorter of the two texts, so short texts have to match more closely than long ones. The default (0.6) accepts ordinary typos while rejecting unrelated short words.

Argument | Type | Description | Default
---------|------|-------------|---------
text | `Text` | The text to find a match for.  | -
candidates | `[Text]` | The candidate texts to choose from.  | -
max_distance | `Num` | The maximum edit distance per grapheme of the shorter text.  | `0.6`

**Return:** The closest candidate, or `none` if `candidates` is empty or nothing is within `max_distance`.


**Example:**
```tomo
commands := ["build", "run", "test"]
assert "bulid".nearest(commands) == "build"
assert "frobnicate".nearest(commands) == none
assert "x".nearest([]) == none

```
## Text.quoted

```tomo
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:**
```tomo
assert "one\ntwo".quoted() == "\"one\\ntwo\""

```
## Text.repeat

```tomo
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:**
```tomo
assert "Abc".repeat(3) == "AbcAbcAbc"

```
## Text.replace

```tomo
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:**
```tomo
assert "Hello world".replace("world", "there") == "Hello there"

```
## Text.reversed

```tomo
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:**
```tomo
assert "Abc".reversed() == "cbA"

```
## Text.right_pad

```tomo
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:**
```tomo
assert "x".right_pad(5) == "x    "
assert "x".right_pad(5, "ABC") == "xABCA"

```
## Text.slice

```tomo
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:**
```tomo
assert "hello".slice(2, 3) == "el"
assert "hello".slice(to=-2) == "hell"
assert "hello".slice(from=2) == "ello"

```
## Text.split

```tomo
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:**
```tomo
assert "one,two,,three".split(",") == ["one", "two", "", "three"]
assert "abc".split() == ["a", "b", "c"]

```
## Text.split_any

```tomo
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:**
```tomo
assert "one, two,,three".split_any(", ") == ["one", "two", "three"]

```
## Text.starts_with

```tomo
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:**
```tomo
assert "hello world".starts_with("hello")
remainder : Text
assert "hello world".starts_with("hello", &remainder)
assert remainder == " world"

```
## Text.title

```tomo
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:**
```tomo
assert "amélie".title() == "Amélie"

# In Turkish, uppercase "i" is "İ"
assert "i".title(language="tr_TR") == "İ"

```
## Text.to

```tomo
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:**
```tomo
assert "goodbye".to(3) == "goo"
assert "goodbye".to(-2) == "goodby"

```
## Text.translate

```tomo
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:**
```tomo
text := "A <tag> & an ampersand".translate({
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': "&quot",
    "'": "&#39;",
})
assert text == "A &lt;tag&gt; &amp; an ampersand"

```
## Text.trim

```tomo
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:**
```tomo
assert "   x y z    \n".trim() == "x y z"
assert "one,".trim(",") == "one"
assert "   xyz   ".trim(right=no) == "xyz   "

```
## Text.upper

```tomo
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:**
```tomo
assert "amélie".upper() == "AMÉLIE"

# In Turkish, uppercase "i" is "İ"
assert "i".upper(language="tr_TR") == "İ"

```
## Text.utf16

```tomo
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:**
```tomo
assert "Åke".utf16() == [197, 107, 101]
assert "こんにちは世界".utf16() == [12371, 12435, 12395, 12385, 12399, 19990, 30028]

```
## Text.utf32

```tomo
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:**
```tomo
assert "Amélie".utf32() == [65, 109, 233, 108, 105, 101]

```
## Text.utf8

```tomo
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:**
```tomo
assert "Amélie".utf8() == [65, 109, 195, 169, 108, 105, 101]

```
## Text.width

```tomo
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:**
```tomo
assert "Amélie".width() == 6
assert "🤠".width() == 2

```
## Text.without_prefix

```tomo
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:**
```tomo
assert "foo:baz".without_prefix("foo:") == "baz"
assert "qux".without_prefix("foo:") == "qux"

```
## Text.without_suffix

```tomo
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:**
```tomo
assert "baz.foo".without_suffix(".foo") == "baz"
assert "qux".without_suffix(".foo") == "qux"

```