Global builtins reference

Around 95 functions are always in scope, with no import.

Collections

Transform: map, filter, reduce, flatten, zip, enumerate, chunk, window, unique, reverse, sort, sort_by, group_by, partition, frequencies, select.

Access: first, last, take, get, len, contains, index_of, find, count, any, all, sum, min, max, empty_map, keys, values.

Build: push, pop, insert, remove, range, list.

Parallel: pmap.

get is the nullable lookup - get(m, k) and get(xs, i) return null on a miss, where m.k and xs[i] raise. See Structured data access.

Strings

upper, lower, trim, split, join, replace, contains, starts_with, ends_with, chars, lines, reverse, index_of, len, escape_html.

is_blank is not a global - it lives in std.string.

The full toolkit is std.string.

Numbers and conversion

int, float, decimal, bool, string, bytes, abs, floor, ceil, round, pow, sqrt, min, max, sum, approx, type_of, is_null.

approx(a, b, eps?) is tolerance comparison for floats - == on floats is exact IEEE. See Numbers.

JSON

json_encode, json_decode. File forms are in std.json.

AI

embed, embed_all, cosine, tokens, cost, retry, session, uuid.

See Embeddings, Budgeting, Retry, Sessions.

Concurrency

cell, cell_get, cell_set, cell_update, channel, send, recv, try_recv, close, select, cancel, sleep, pmap.

See cell and Channels.

Secrets

secret, reveal, is_secret. See Secrets.

Errors and assertions

error, assert. See Error handling.

Output

print, print_no_newline, read_file, write_file.

Python escape hatch

result = py("[x*2 for x in range(5)]")

py(...) evaluates Python in a persistent worker process, for the case where a library exists there and nowhere else. It is the deliberate escape hatch: reaching for it stays inside your Ecko program rather than becoming a separate service.

It needs Python on the machine, which is the one place Ecko's "one binary, nothing to install" promise does not reach - so treat it as a bridge, not a foundation.

Shadowing

Assigning to a builtin name shadows it in the current scope rather than erroring, so sum = 0 is always safe. ecko check warns, because it is usually accidental. Reach the original through core.*:

export fn get(c, key) { ... }
fn internal(m, k) = core.get(m, k)

Arity

Every builtin's arity is checked at the call site by ecko check, before the program runs - so a wrong argument count is caught rather than raising mid-run.