TYCHO Search

Search documentation

    ↑ ↓ to move · Enter to open · Esc to close

    Builtins

    Memory: builtins follow the same ownership rules as everything else. A builtin that builds a value hands it to the caller.

    The built-in functions, by category. These are part of the language — always there, no import needed; the importable corelib layers more on top. Anything written as an operator or keyword (m[k], k in m, delete, for x in xs) lives on its own topic page.

    Output and input

    BuiltinTypeNotes
    print(s)string -> voidNo implicit newline; add "\n".
    println(s)string -> voidprint(s) plus a trailing newline. String-only, like print — use println(str(x)) for non-strings.
    input()-> stringOne line from stdin (newline stripped).
    read_all()-> stringAll of stdin as one string.
    args()-> [string]Command-line arguments; args()[0] is the program name.
    getenv(name)string -> stringThe variable's value, or "" if unset.
    die(msg)string -> voidPrint msg to stderr and exit with status 1.
    exit(code)int -> voidTerminate with status code, printing nothing; never returns. exit(0) is an ordinary answered exit, not a failure.

    input() cannot distinguish EOF from a blank line: both return "". When that matters, use io.open_lines / io.read_line, whose None is EOF.

    print/println are stdio-backed. When stdout is a pipe or file, the buffer may not reach the reader until the process exits; call io.flush_stdout() when the reader must see a line while the program is still running.

    Conversions

    BuiltinTypeNotes
    str(x)int, sized ints, f32, bool, float, string, char -> stringA finite float prints as a decimal with at most 17 significant digits that reads back as the same float (the formatter tries 15, 16, then 17 and keeps the first that round-trips); fixed notation uses a ., exponent forms (e±NN) may omit it. A bool prints true/false. NaN and the infinities are the exception — see below.
    to_float(n)numeric scalar -> floatWiden or reinterpret through the scalar base.
    to_int(x)float, sized int, f32, char, or int-newtype -> intTruncate a float toward zero; sized ints/char convert by value; int-newtype unwraps.
    to_bytes(s) / to_str(b)string <-> bytesSame byte buffer; bytes may carry interior NULs.
    to_bytes(xs)[int] -> bytesEach element & 0xFF into a fresh buffer — builds a binary bytes (interior NULs and all) that a string can't hold.
    to_bytes(v)packed struct -> bytesExactly size_of$(T) bytes, little-endian, fields in declaration order.
    size_of$(T)-> intThe byte size of a packed struct, exact. Also takes an align(N) struct, whose size is implementation-defined but a multiple of N.
    from_bytes$(T)(b)bytes -> TRead a packed struct back. len(b) must equal size_of$(T) exactly; any other length aborts, naming the type and both lengths.
    chr(n)int -> stringThe one-byte string for byte value n (0–255).
    to_char(n)int -> charThe byte value n as a char. Outside 0..255 it aborts — where chr(n) returns a one-byte *string*, this returns a char.

    NaN and the infinities do not round-trip. str hands those three to the host C library, which on glibc spells them -nan, inf and -inf — no decimal point, and not the same text on every platform. strings.parse_float refuses all three by design, so a float written with str and read back with parse_float survives only if it was finite. x == x is false for exactly NaN, and x - x == 0.0 is false for exactly NaN and the infinities, which is how to check before serialising.

    (A newtype's to_int / to_float / to_str / to_bool / to_under unwrappers are on the Types page.)

    Strings

    Strings are byte buffers; len, s[i], substr, and find are all byte-oriented (not Unicode-aware). String escapes: \n \t \r \\ \" — those five and no others, with the char set and the rejected spellings on the Types page.

    BuiltinTypeNotes
    len(s)string -> intByte length.
    substr(s, a, b)(string, int, int) -> stringSubstring [a, b), a fresh copy. Out-of-range bounds are clamped, not an error.
    find(s, sub)(string, string) -> intByte index of the first sub, or -1.
    char_at(s, i)(string, int) -> charThe byte at i as a char — the same read and the same bounds abort as s[i].
    split(s, sep)(string, string) -> [string]Split on a non-empty separator; n separators yield n+1 fields. An empty separator aborts.

    Arrays

    BuiltinTypeNotes
    len(a)[T] -> intElement count.
    push(a, v)([T], T) -> voidAppend in place (needs a mutable array).
    pop(a)[T] -> TRemove and return the last element; aborts if empty.
    reserve(a, n)([T], int) -> voidCapacity hint (also works on a map place m[k]): preallocate room for n. A hint, not a length — len is unchanged and pushing past n still grows; an unallocatable capacity aborts.

    Maps

    len(m), m[k] = v, k in m, delete m[k], and keys(m) are documented on the Maps page. The default-valued read is a method on the map:

    BuiltinTypeNotes
    m.get(k, d)(map, K, V) -> VValue for k, or default d if absent. m.get(k) is m[k] (value-type zero on a miss).
    hash(x)K -> int for any map-key typeThe hash the maps themselves use, exposed: values equal by == hash equal. Returns the full 64-bit value.

    Concurrency

    See Concurrency for semantics.

    BuiltinTypeNotes
    wait(t)Task(T) -> TJoin a spawned task (the result is copied out). Each task can be waited exactly once.
    ncpu()-> intOnline CPUs, or TYCHO_THREADS when set to an integer >= 1. The *requested* worker count, not the number of parallel tasks: parallel for caps at 64 chunk tasks.
    channel(T, cap)-> Channel(T)A bounded lock-free queue (cap rounds up to a power of two). Legal only as a declaration's direct right-hand side.
    send(ch, v)(Channel(T), T) -> voidCopy v in; blocks when full; aborts if closed.
    recv(ch)Channel(T) -> Option(T)Blocking receive (copied out); None means closed and drained.
    close(ch)Channel(T) -> voidReceivers drain then see None; a further send or second close aborts.
    close(h)handle -> voidOn a typed FFI handle variable: run its destructor now and null it, so the scope-exit free does not run it again. A handle parameter is a borrow and cannot be closed (a compile error); close it in the scope that owns it. Any later mention of h in the same block (a second close included) is a compile error; a close inside an if or loop reaches only that block's end. See typed handles.

    Filesystem and time

    BuiltinTypeNotes
    read_file(path)string -> stringWhole file as a string, or "" if it can't be opened.
    write_file(path, s)(string, string) -> boolWrite s's exact bytes (truncating); false if it can't be opened.
    list_dir(path)string -> [string]Entries excluding ./.. (filesystem order); empty if it can't be opened.
    clock()-> intMonotonic nanoseconds (differences are meaningful; the absolute value is not).
    now()-> intWall-clock seconds since the UNIX epoch.

    read_file is fail-open by design: a missing file, an unreadable file and a genuinely empty file all return "". When that distinction matters, use core:io.read_text(p) -> Result(string, io.IoErr) or read_bytes(p) instead.

    Float math (libm)

    BuiltinType
    sqrt(x) / pow(x, y) / floor(x) / fabs(x)float… -> float

    FFI and sized-integer helpers

    Supporting the FFI boundary and the sized numeric types; always available, no import.

    BuiltinTypeMeaning
    eprint(s)string -> voidWrite s to standard error (no newline, no exit).
    eprintln(s)string -> voidWrite s and a trailing newline to standard error.
    is_null(p)ptr -> bool, handle -> boolTest an opaque FFI ptr, or a typed handle, for null. On a handle: true when the opener failed, and true after close(h). After a close(h) statement in the same block it is a compile error (it could only be true); after a close in a branch it cannot tell "closed" from "never opened".
    to_ptr(n)int -> ptrMake a sentinel ptr from an int (e.g. (void*)-1); Tycho never dereferences it.
    to_i32(n)int -> i32Explicitly narrow to the signed 32-bit integer type.
    to_u32(x) / to_u64(x) / to_f32(x)numeric -> u32/u64/f32Convert any numeric scalar to the sized type.