Tanguv0.32.0
/prelude

Prelude & core built-ins

Special forms, universal sequence accessors, core types, arithmetic/bitwise operators, and derivable traits.

Special forms & declarations #

Core syntactic forms built into the Tangu compiler and evaluator.

def #

(def name value)

Declares a top-level or hoisted binding (function, struct, trait, or constant). Stack attributes like #pub, #inline, and #test on lines above (def ...).

(def add (Func [a b] (+ a b)))

let #

(let pattern value)

Binds a local immutable variable (or rebindable #var / mutable #mut binding) sequentially within the current lexical scope. Supports array [a b] and map {:x} destructuring.

(let [first ...rest] [10 20 30])

Func #

(Func params body...)

Constructs a first-class lexical closure. Parameter forms: () for zero args, x for single arg, or [a b ...rest] for multiple/typed/destructured args.

(let double (Func x (* x 2)))

Struct #

(Struct #Type #{constraints}? field (#Type field default) ...)

Defines a nominal product type with typed fields, optional default values, and declarative validation constraints.

(def Point (Struct #Int x #Int y))

Trait #

(Trait #(Func [This ...] Ret) (method (Func [this ...])) ...)

Defines a polymorphic trait interface that can be implemented for structs or built-in types via impl.

(def Printable (Trait #(Func This String) (format (Func this))))

impl #

(impl Trait-Name Target-Type (let method (Func [self ...] ...)))

Implements a Trait for a target Struct or type.

(impl Printable Point (let format (Func self "${self:x},${self:y}")))

derive #

(derive Struct-Type Trait1 Trait2 ...)

Automatically synthesizes standard trait implementations (Eq, Hash, Ord, Clone, To-String, Default, To-JSON, From-JSON) for a Struct.

(derive Point Eq Hash Ord Clone To-String Default)

use #

(use {sym1 sym2} /module/path)

Imports a module or selective symbol bindings from @standard (/path), a package (@scope/pkg), or a relative path (./mod). Supports #lazy deferred loading.

(use {join split} /string)

<- #

(<- target new-value)

Reassigns a #var binding or updates a #mut struct field / collection element in place (+<- increments in place).

(let #var x 1)
(<- x 2)

#lazy / #static #

(let #lazy x expr), (let #static cache expr)

#lazy defers evaluation of a binding or (use #lazy ...) module until first access; #static evaluates a function-local binding once and caches it across calls.

(let #static lookup-table {:a 1 :b 2})

%file / %dir / %module / %profile #

%file, %dir, %module, %profile

Compile-time context intrinsics expanding to the current source file path (%file), parent directory (%dir), module path (%module), and active build profile (%profile).

(let config-path "${%dir}/config.data.tan")

Control flow & pattern matching #

Branching, structural pattern matching, iteration, and early-return error handling.

if #

(if cond then-body... (else else-body...))

Evaluates cond (which must be a strict Bool); runs then-body when true or the optional (else ...) block when false.

(if (> x 0) "positive" (else "non-positive"))

unless #

(unless cond body...)

Executes body when cond evaluates to false.

(unless (is-empty? items) (process items))

cond #

(cond test1 expr1 test2 expr2 _ default-expr)

Multi-branch conditional evaluating flat test expr pairs in order; _ provides the fallback arm.

(cond (== code 200) :ok (== code 404) :not-found _ :error)

when #

(when target pattern1 expr1 ... _ default-expr)

Structural pattern matching over literals, runtime types (Int, String, Error), arrays ([x ...xs]), and maps ({:status 200}).

(when resp {:status 200 :body b} b Error "failed" _ "other")

for #

(for [binding seq] body...)

Iterates over any sequence, range, map, or iterator for side effects. Supports [item seq] and [[key val] map].

(for [x 0..5] (say x))

for->seq #

(for->seq [binding seq] body...)

List/Array comprehension collecting the result of each iteration into a new Array. Call (continue) to skip an element.

(for->seq [x [1 2 3]] (* x 10)) ; => [10 20 30]

while #

(while cond body...)

Repeatedly evaluates body while cond remains true. Supports (break) and (continue).

(while (< i 10) (+<- i 1))

try #

(try expr (else fallback-return-expr))

Unwraps a computation if it is Some (neither () nor Error); on Error or (), strictly early-returns the failure or the (else ...) value from the enclosing function.

(let data (try (decode raw-json)))

some-or #

(some-or cand1 ... default-expr)

Short-circuiting local fallback for () (None): returns the first non-() candidate, or default-expr (passes Error values through unchanged).

(let port (some-or config?port 8005))

ok-or #

(ok-or cand1 ... fallback-expr)

Short-circuiting local fallback for both Error and () (None): returns the first valid candidate, or fallback-expr without early-returning from the function.

(let parsed (ok-or (Int input) 0))

|> #

(|> initial-value (step1 %0) (step2 %0 arg) ...)

Pipeline operator threading the result of each expression into %0 (or %) of the next step.

(|> "  hello  " (trim %0) (to-upper-case %0)) ; => "HELLO"

Universal sequence & collection intrinsics #

Polymorphic functions available without imports across Array, List, String, Map, Set, Range, and Slab.

count-of #

(count-of coll) -> Int

Returns the number of elements in a collection, Unicode scalar values in a String, or delegates to the Countable trait.

(count-of [10 20 30]) ; => 3

byte-count-of #

(byte-count-of str-or-slab) -> Int

Returns the exact UTF-8 byte length of a String or byte length of a Slab in O(1) time.

(byte-count-of "café") ; => 5

is-empty? #

(is-empty? coll) -> Bool

Returns true if coll has zero elements (count-of == 0).

(is-empty? []) ; => true

contains? #

(contains? coll item) -> Bool

Checks element membership in an Array/List/Set/Range, substring presence in a String, key presence in a Map, or invokes the Contains trait.

(contains? [1 2 3] 2) ; => true

contains-key? #

(contains-key? map key) -> Bool

Returns true if map contains key.

(contains-key? {:a 1} :a) ; => true

first-of #

(first-of seq) -> (Or Any None)

Returns the first element of seq, or () if empty.

(first-of [10 20 30]) ; => 10

last-of #

(last-of seq) -> (Or Any None)

Returns the last element of seq, or () if empty.

(last-of [10 20 30]) ; => 30

nth-of #

(nth-of seq index) -> (Or Any None)

Returns the element at zero-based index (supporting negative indices from the end).

(nth-of [10 20 30] 1) ; => 20

rest-of #

(rest-of seq) -> Array

Returns a slice containing all elements after the first.

(rest-of [1 2 3]) ; => [2 3]

slice #

(slice seq start end?) -> Seq

Extracts a sub-slice from start up to end (supporting negative offsets like -1).

(slice [10 20 30 40] 1 -1) ; => [20 30]

byte-slice #

(byte-slice str-or-slab start end) -> String | Slab

Extracts a zero-copy or O(k) byte range [start..end) from a String or Slab.

(byte-slice "hello world" 0 5) ; => "hello"

reverse #

(reverse seq) -> Seq

Returns a new Array, List, or String with elements in reverse order.

(reverse [1 2 3]) ; => [3 2 1]

concat #

(concat seq1 seq2 ...) -> Seq

Concatenates multiple arrays, lists, or strings into a single sequence.

(concat [1 2] [3 4]) ; => [1 2 3 4]

push #

(push #mut array item...) -> Array

Appends one or more elements to the end of a mutable Array.

(let #mut a [1])
(push a 2 3)

pop #

(pop #mut array) -> (Or Any None)

Removes and returns the last element of a mutable Array.

(pop a)

put #

(put #mut coll key-or-item value?) -> Coll

Inserts or updates a key-value pair in a mutable Map, or inserts an element into a Set.

(put m :status :ready)

put-all / put-many #

(put-all #mut coll source-coll), (put-many #mut map [k1 v1] [k2 v2] ...)

Merges all entries from source-coll (put-all) or multiple [key value] pairs (put-many) into a mutable Map or Set.

(put-all m {:host "127.0.0.1" :port 8005})

remove / swap-remove #

(remove #mut coll key-or-index) -> Any, (swap-remove #mut array index) -> Any

remove deletes and returns an entry by key (Map/Set) or index (Array); swap-remove removes an Array element in O(1) time by swapping it with the last element.

(remove m :status)

keys-of #

(keys-of map) -> Array

Returns an Array of all keys in map.

(keys-of {:a 1 :b 2})

values-of #

(values-of map) -> Array

Returns an Array of all values in map.

(values-of {:a 1 :b 2})

entries-of #

(entries-of map) -> Array

Returns an Array of [key value] pairs from map.

(entries-of {:a 1}) ; => [[:a 1]]

sort / sort<- #

(sort array) -> Array, (sort<- #mut array) -> Array

sort returns a sorted copy of array using natural Ord comparison; sort<- sorts a #mut array in place.

(sort [3 1 2]) ; => [1 2 3]

sort-by #

(sort-by array key-or-cmp-fn) -> Array

Sorts array by a key-extractor function (Func x key) or comparator (Func [a b] Int).

(sort-by users (Func u u:age))

reverse<- / concat<- / roll #

(reverse<- #mut array), (concat<- #mut array other), (roll seq offset)

In-place array reversal (reverse<-), in-place array extension (concat<-), and circular element rotation (roll).

(roll [1 2 3 4] 1) ; => [4 1 2 3]

map #

(map seq fn) -> Array

Applies fn to each element of seq and returns a new Array.

(map [1 2 3] (* %0 2)) ; => [2 4 6]

filter #

(filter seq pred-fn) -> Array

Returns a new Array containing elements of seq for which pred-fn returns true.

(filter [1 2 3 4] (> %0 2)) ; => [3 4]

collect #

(collect seq-or-iter) -> Array

Materializes any lazy iterator, range, set, or sequence into a contiguous Array.

(collect 0..5) ; => [0 1 2 3 4]

String intrinsics #

Built-in UTF-8 string search, splitting, replacement, and case conversion.

trim #

(trim str) -> String

Strips leading and trailing whitespace (trim-start and trim-end strip one side).

(trim "  hi  ") ; => "hi"

split #

(split str delimiter) -> (Array String)

Splits str around delimiter into an Array of substrings.

(split "a,b,c" ",") ; => ["a" "b" "c"]

join #

(join array separator?) -> String

Joins elements of array into a single String separated by separator.

(join ["a" "b"] "-") ; => "a-b"

replace #

(replace str pattern replacement) -> String

Replaces all occurrences of pattern in str with replacement (replace-first replaces only the first).

(replace "foo-bar" "-" "_") ; => "foo_bar"

starts-with? #

(starts-with? str prefix) -> Bool

Returns true if str starts with prefix.

(starts-with? "/stdlib-web" "/stdlib") ; => true

ends-with? #

(ends-with? str suffix) -> Bool

Returns true if str ends with suffix.

(ends-with? "main.tan" ".tan") ; => true

to-lower-case #

(to-lower-case str) -> String

Converts str to lowercase Unicode characters.

(to-lower-case "Tangu") ; => "tangu"

to-upper-case #

(to-upper-case str) -> String

Converts str to uppercase Unicode characters.

(to-upper-case "tangu") ; => "TANGU"

Types, introspection & sized integers #

Runtime type predicates, deep cloning, hashing, and explicit sized integer constructors.

type-of #

(type-of value) -> Symbol

Returns the runtime type name of value (Int, Float, Dec, String, Array, Map, or a Struct name).

(type-of [1 2]) ; => Array

is-a? #

(is-a? Type value) -> Bool

Returns true if value is an instance of Type (or implements trait Type).

(is-a? Int 42) ; => true

is-some? #

(is-some? value) -> Bool

Returns true if value is neither () (None) nor an Error.

(is-some? 0) ; => true

is-none? #

(is-none? value) -> Bool

Returns true if value is () (None).

(is-none? ()) ; => true

is-error? #

(is-error? value) -> Bool

Returns true if value is an Error.

(is-error? (Error :fail "msg")) ; => true

clone #

(clone value) -> Any

Returns a deep structural copy of value, duplicating mutable collections and structs.

(let copy (clone original))

hash #

(hash value) -> Int

Computes the deterministic 64-bit hash of any value or Struct implementing Hash.

(hash {:a 1 :b 2})

I8 / I16 / I32 / I64 / I128 / ISize #

12i8, 123i16, 12_345i32, -10isize, (I32 val) -> I32

Signed sized integer literal suffixes and constructors wrapping modulo the bit width (8, 16, 32, 64, 128, or pointer width).

(let offset 12_345i32)

U8 / U16 / U32 / U64 / U128 / USize #

255u8, 8005u16, 1000usize, (U8 val) -> U8

Unsigned sized integer literal suffixes and constructors (U8 is also aliased as Byte).

(let port 8005u16)

cast #

(cast Target-Type value) -> Target-Type

Performs an explicit numeric or structural type conversion to Target-Type.

(cast Float 42) ; => 42.0

Core & derivable traits #

Built-in traits supported by (derive My-Struct ...) and custom (impl Trait My-Struct ...).

Eq #

(derive My-Struct Eq)

Structural equality comparison via (== a b) and (!= a b).

(derive Point Eq)

Ord #

(derive My-Struct Ord)

Total ordering comparison via <, <=, >, >=, and sort.

(derive Point Eq Ord)

Hash #

(derive My-Struct Hash)

Deterministic hashing via (hash x), enabling use as Map keys and Set elements.

(derive Point Eq Hash)

Clone #

(derive My-Struct Clone)

Deep structural duplication via (clone x).

(derive Point Clone)

To-String #

(derive My-Struct To-String)

Human-readable string conversion via (String x) and string interpolation.

(derive Point To-String)

Default #

(derive My-Struct Default)

Zero-argument default construction via (construct-default My-Struct).

(derive Point Default)

Countable #

(def Countable (Trait #(Func This Int) (count-of (Func this))))

Custom length/size reporting for (count-of x) and (is-empty? x).

(impl Countable Queue (let count-of (Func self (count-of self:items))))

Contains #

(def Contains (Trait #(Func [This Any] Bool) (contains? (Func [this item]))))

Custom membership testing for (contains? x item).

(impl Contains Span (let contains? (Func [self v] (and (>= v self:lo) (<= v self:hi)))))

To-JSON / From-JSON #

(derive My-Struct To-JSON From-JSON)

Zero-boilerplate JSON serialization with (encode x) and typed deserialization with (from-json My-Struct data) or (decode raw My-Struct).

(derive Point To-JSON From-JSON)

Arithmetic, bitwise & math intrinsics #

Numeric operators and transcendental functions available in the prelude.

+ / - / * / / / % / ** #

(+ a b ...), (- a b), (* a b ...), (/ a b), (% a b), (** base exp)

Arithmetic addition, subtraction, multiplication, division, remainder (%), and exponentiation (**) across Int, Float, Dec, and sized integers.

(+ 10 20 30) ; => 60

== / != / < / <= / > / >= #

(== a b), (!= a b), (< a b), (<= a b), (> a b), (>= a b)

Equality and relational ordering comparisons returning Bool.

(<= 10 20) ; => true

and / or / not #

(and a b ...), (or a b ...), (not a)

Short-circuiting boolean conjunction (and), disjunction (or), and negation (not).

(and (> x 0) (< x 100))

abs / min / max / clamp #

(abs x), (min a b), (max a b), (clamp x lo hi)

Absolute value, minimum, maximum, and range clamping.

(clamp 150 0 100) ; => 100

floor / ceil / round / trunc #

(floor x), (ceil x), (round x), (trunc x)

Floating-point and decimal rounding functions.

(round 3.6) ; => 4.0

sqrt / sin / cos / tan / log / exp #

(sqrt x), (sin x), (cos x), (tan x), (log x), (exp x)

Square root, trigonometric functions, natural logarithm, and exponential.

(sqrt 16.0) ; => 4.0

bit-and / bit-or / bit-xor / bit-not / bit-shl / bit-shr #

(bit-and a b), (bit-or a b), (bit-xor a b), (bit-shl x n), (bit-shr x n)

Bitwise AND, OR, XOR, NOT, left shift (bit-shl), and arithmetic/logical right shift (bit-shr).

(bit-shl 1 8) ; => 256

I/O, data parsing & assertion intrinsics #

Console output, safe .data.tan loading, AST parsing, and test assertions.

say / echo #

(say value...), (echo value...)

say prints arguments to stdout followed by a newline; echo prints without a trailing newline.

(say "Listening on port ${port}")

read / write #

(read path) -> String, (write path content) -> None

Convenience prelude functions to read a UTF-8 file into a String or write a String to disk.

(let text (read "readme.text"))

read-data / load-data #

(read-data str) -> Any, (load-data path) -> Any

Safely parses a pure .data.tan literal from a string or file without evaluating executable calls.

(let manifest (load-data "manifest.data.tan"))

parse-expr / parse-exprs #

(parse-expr str) -> Expr, (parse-exprs str) -> (Array Expr)

Parses Tangu source code into homoiconic s-expression AST nodes.

(let ast (parse-expr "(+ 1 2)"))

assert / assert-eq! / assert-ne! #

(assert cond msg?), (assert-eq! left right), (assert-ne! left right)

Test and invariant assertions that panic with source location and diff details when violated.

(assert-eq! (+ 2 2) 4)

panic! #

(panic! message)

Immediately aborts the current evaluation or test with message.

(panic! "unreachable state")