Contents

Stdlib reference (mere)

106 builtins that are always available via initial_env. Check a name's type with mere -te NAME.

Legend:

Sugar / prelude added in Phase 36 (2026-06-22)

Syntactic sugar (13): lexer / parser-level changes only; preserves 4-backend compatibility:

Prelude additions (16 of 34 entries added in Phase 36):


I/O (10)

NameTypeDescription
printstr -> unitWrite to stdout with newline
print_no_nlstr -> unitWithout newline + flush (for prompts)
print_intint -> unitPrint integer with newline
print_boolbool -> unitPrint bool with newline
print_errstr -> unitWrite to stderr with newline
read_lineunit -> strOne line from stdin; empty string on EOF
read_filestr -> strRead the whole file; raises on failure
write_filestr -> str -> unitWrite content to path (overwrite); raises on failure
read_lines ⚡ ★str -> str listRead line by line, returns str list (Phase 19.6; depends on prelude)
file_existsstr -> boolWhether path exists (Phase 19.6)
env_varstr -> str optionFetch env var; None if unset (Phase 19.6; depends on prelude)
argsunit -> str listargv[1..] at program startup (Phase 19.6)

file_exists "/etc/hosts"            // → true
env_var "PATH"                      // → Some "..."
env_var "BOGUS"                     // → None
read_lines "data.txt"               // → ["line1", "line2", ...]
args ()                             // → ["foo", "bar"] (mere prog -- foo bar)

★ Codegen status: print / print_no_nl / print_int / print_bool / print_err / read_file / write_file work in all 3 backends (Wasm goes through host imports; scripts/run_wasm.js provides puts / read_file / write_file). read_lines / args / env_var / file_exists are interpreter-only (codegen would need 'a list / 'a option construction + systematic outside-world access; not yet covered by Phases 22-31).


let _ = print "Hello";
let _ = print_no_nl "Name: ";
let name = read_line () in print ("Hi, " ++ name);

// File round-trip
let _ = write_file "/tmp/out.txt" "hello lang";
let content = read_file "/tmp/out.txt" in print content;

Value conversion (3)

NameTypeDescription
str_of_intint -> strInteger to string
int_of_strstr -> intParse after trim; raises on bad input
bool_of_strstr -> boolTrim then "true"/"false" only; raises otherwise
float_of_intint -> floatint → float (no precision loss)
int_of_floatfloat -> intfloat → int (truncation)
str_of_floatfloat -> strFloat to string (OCaml semantics)
float_of_strstr -> floatParse after trim; raises on bad input

str_of_int 42        // "42"
int_of_str "  -7  "  // -7
bool_of_str "true"   // true

String operations (22)

NameTypeDescription
str_lenstr -> intByte length
str_containsstr -> str -> boolSubstring containment
str_starts_withstr -> str -> boolPrefix test
str_ends_withstr -> str -> boolSuffix test
str_countstr -> str -> intNon-overlapping occurrence count
str_index_ofstr -> str -> intFirst position of needle; -1 if not found. Empty needle returns 0 (Phase 19.1)
str_splitstr -> str -> str listSplit by delimiter; returns str list. Requires type 'a list = ... declared. Empty delimiter returns a single-element list (Phase 19.1)
str_joinstr -> str list -> strJoin with separator. Empty list → empty string (Phase 19.1)
str_compare 🌐str -> str -> intLexicographic -1 / 0 / 1 (Phase 31.0 ported to 3 backends; sign-normalized)
str_repeatstr -> int -> strRepeat N times; raises on N<0
str_replacestr -> str -> str -> strReplace all; empty needle = no change
str_revstr -> strReverse string
str_trimstr -> strStrip leading/trailing whitespace
str_unescapestr -> strDecode \n \t \r \\ \" \/; raises on unknown escape
substringstr -> int -> int -> strs[start:end_excl]; raises on out of range
char_atstr -> int -> strIndex access (length-1 str); raises on OOB
chrint -> strint in 0..255 to single-char str; raises out of range
ordstr -> intSingle-char str to int code point; raises if length != 1
to_upperstr -> strASCII uppercase
to_lowerstr -> strASCII lowercase
is_digitstr -> boolTrue for single char in '0'..'9'; otherwise false
is_alphastr -> boolTrue for single char that's a letter
is_spacestr -> boolTrue for single char that's space/tab/\n/\r

type 'a list = Nil | Cons of 'a * 'a list;
str_split "a,b,c" ","                          // ["a", "b", "c"]
str_join "-" ["alpha", "beta", "gamma"]        // "alpha-beta-gamma"
str_index_of "hello world" "world"             // 6
str_index_of "hello" "xyz"                     // -1

★ Codegen status: str_index_of / str_split / str_join / str_count / str_compare / str_trim / str_starts_with / str_ends_with / str_contains / str_replace / str_repeat / str_rev all work across all 4 backends (Phase 19.1.1 added str_index_of; Phase 22 added str_split / str_join; Phase 26.5 added all Wasm str ops; Phase 31.0 added str_compare; Phase 36 added str_trim / starts_with / ends_with / contains / replace / repeat / rev). not / abs / min / max / clamp / chr / ord / to_upper / to_lower / even / odd / gcd / bool_of_str also reached the 3 backends in Phase 36. The fn (_: unit) -> body wildcard parameter was also parser-fixed in Phase 36.


str_replace "foo bar foo" "foo" "X"           // "X bar X"
substring "hello world" 6 11                  // "world"
char_at "abcdef" 2                            // "c"
"world" |> str_contains "hello world"         // true (pipe + curry)
str_unescape "a\\nb"                          // a + newline + b (3 chars)

Numeric operations (17)

NameTypeDescription
minint -> int -> intSmaller
maxint -> int -> intLarger
absint -> intAbsolute value
signint -> int-1 / 0 / 1
clampint -> int -> int -> intclamp lo hi x restricts to [lo, hi]
powint -> int -> intbase^exp; raises on negative exp
squareint -> intx x
cubeint -> intx x x
incrint -> int+1
decrint -> int-1
evenint -> booln mod 2 == 0
oddint -> booln mod 2 != 0
gcdint -> int -> intEuclid (handles negatives and 0 correctly)
lcmint -> int -> inta/gcd b; 0 in input → 0
divmodint -> int -> (int * int)(quotient, remainder); raises on 0 div
sum_rangeint -> int -> intSum over lo..hi (Gauss formula, O(1))
notbool -> boolLogical negation

Float arithmetic (4)

NameTypeDescription
f_addfloat -> float -> floatAddition
f_subfloat -> float -> floatSubtraction
f_mulfloat -> float -> floatMultiplication
f_divfloat -> float -> floatDivision (IEEE 754: 0 div is inf/nan)
f_ltfloat -> float -> boolLess than
f_lefloat -> float -> boolLess than or equal
f_gtfloat -> float -> boolGreater than
f_gefloat -> float -> boolGreater than or equal
f_negfloat -> floatUnary minus (Neg is int-only, so use this for float)
f_absfloat -> floatAbsolute value
sqrtfloat -> floatSquare root (NaN for negatives)
floorfloat -> floatFloor
ceilfloat -> floatCeiling
roundfloat -> floatRound
f_minfloat -> float -> floatSmaller (Phase 19.7)
f_maxfloat -> float -> floatLarger (Phase 19.7)
f_powfloat -> float -> floatPower base ^ exp (Phase 19.7)
logfloat -> floatNatural log (Phase 19.7)
expfloat -> floate^x (Phase 19.7)
sinfloat -> floatSine (radians; Phase 19.7)
cosfloat -> floatCosine (Phase 19.7)
tanfloat -> floatTangent (Phase 19.7)
atan2float -> float -> floatatan2 y x for angle (Phase 19.7)
random_int ★ ⚡int -> intrandom_int n returns int in 0..n-1; raises if n<=0 (Phase 19.7)
random_floatunit -> floatFloat in [0.0, 1.0) (Phase 19.7)
pifloatπ ≈ 3.14159265 (constant builtin)
efloate ≈ 2.71828183 (constant builtin)

★ Codegen status: the 11 entries added in Phase 19.7 are interpreter-only. Codegen support requires libm linking or per-backend wiring of built-in math functions, planned for a follow-up slice (19.7.1).


f_add 1.5 2.5                    // 4.0
f_div 10.0 4.0                   // 2.5
3.14 |> f_mul 2.0                // 6.28

clamp 0 100 150                  // 100
pow 2 10                         // 1024
gcd 12 18                        // 6
sum_range 1 100                  // 5050
fst (divmod 100 7) + snd (divmod 100 7)   // 14 + 2

Control / error (3)

NameTypeDescription
fail ⚡ ★str -> 'aPanic that unifies with any type
assertbool -> str -> unitOn false, raises "assertion failed: MSG"
try_or(unit -> 'a) -> 'a -> 'aEvaluate the thunk; catch Eval_error and return default

let safe = fn s -> try_or (fn () -> int_of_str s) (- 1);
safe "42"      // 42
safe "abc"     // -1

if x < 0 then fail "negative" else x

fail is polymorphic, so type inference works at branch merges (if c then fail msg else int_val → int).


Polymorphic helpers (8 ★)

NameTypeDescription
show'a -> strStringify any value via to_string
id'a -> 'aIdentity function
fst('a * 'b) -> 'aTuple first
snd('a * 'b) -> 'bTuple second
pair'a -> 'b -> ('a * 'b)Tuple constructor (curried)
swap('a * 'b) -> ('b * 'a)Tuple swap
const'a -> 'b -> 'aDrop second arg, return first
flip('a -> 'b -> 'c) -> ('b -> 'a -> 'c)Reverse arg order of a curried fn (higher-order)

show 42                          // "42"
show (Some 5)                    // "Some 5"
show [1, 2, 3]                   // "[1, 2, 3]"   (Cons/Nil chains shown as [..])
show [Some 1, None, Some 3]      // "[Some 1, None, Some 3]"

fst (pair "hi" 42)               // "hi"
let always_7 = const 7 in always_7 "anything"   // 7
let sub = fn a -> fn b -> a - b in (flip sub) 3 10   // 7 (= sub 10 3)

Loop helper (1 ★)

NameTypeDescription
iter_nint -> (unit -> unit) -> unitApply thunk N times (side-effect loop); no-op when N≤0

Capability (2 + 2 builtin record types)

Used by the effect system (see effects.mere). The Logger and Metrics cap types are pre-registered as builtins. Users can also override with their own type Logger = ....


type Logger  = { info: str -> unit, warn: str -> unit, error: str -> unit };
type Metrics = { inc: str -> unit, record: str -> int -> unit };
NameTypeDescription
mk_loggerstr -> LoggerCreate a prefixed Logger. Each field prints as prefix [LEVEL] msg
mk_metricsunit -> MetricsCreate a Metrics. inc / record print as [METRIC] ...

let lg = mk_logger "app" in
{ lg.info "started";
  lg.warn "slow query";
  lg.error "abort" }

let m = mk_metrics () in
{ m.inc "users";
  m.record "latency_ms" 23 }

For a complete cap-passing example see examples/effects.mere.


System / constants (4)

NameTypeDescription
timeunit -> floatUnix epoch seconds (gettimeofday). For benchmarks / timestamps
exitint -> 'aExit the process with an exit code (never returns; polymorphic return)
int_maxintMax int value (OCaml runtime dependent; 2^62-1 on 64-bit) — constant builtin
int_minintMin int value — constant builtin

let start = time () in
{ run_heavy_computation ();
  print ("elapsed: " ++ str_of_float (f_sub (time ()) start) ++ " sec") }

if config_invalid then exit 1 else continue ()

iter_n 3 (fn () -> print "===")   // prints === three times

All builtins (alphabetical, 106)


abs args assert atan2 bool_of_str ceil char_at chr clamp const
cos cube decr divmod e env_var even exit exp f_abs f_add
f_div f_ge f_gt f_le f_lt f_max f_min f_mul f_neg f_pow
f_sub fail file_exists flip float_of_int float_of_str floor
fst gcd id incr int_max int_min int_of_float int_of_str
is_alpha is_digit is_space iter_n lcm log max min mk_logger
mk_metrics not odd ord pair pi pow print print_bool
print_err print_int print_no_nl random_float random_int
read_file read_line read_lines round show sign sin snd sqrt
square str_compare str_contains str_count str_ends_with
str_index_of str_join str_len str_of_float str_of_int
str_repeat str_replace str_rev str_split str_starts_with
str_trim str_unescape substring sum_range swap tan time
to_lower to_upper try_or write_file

Q-010 collection builtins (vec_* / owned_vec_* / strbuf_* / map_* / len) are registered builtins outside this table; see language-reference / tutorial. Phase 19.2 added `map_iter : Map[R, K, V] -> (K -> V -> unit) -> unit` (works in all 4 backends).


See also