Modules & Standard Library


Module System

Eta organises code into modules. Every top-level source file must contain one or more (module …) forms. The module system supports exports, imports with filtering, and incremental REPL execution.

Key sources: module_linker.h · expander.h · driver.h


Module Syntax

(module <name>
  (export <id> ...)           ;; names visible to importers
  (import <module-name>)      ;; import all exported names
  (import (only <mod> <id> ...))
  (import (except <mod> <id> ...))
  (import (rename <mod> (<old> <new>) ...))
  (begin
    (define ...)
    (defun ...)
    ...))

Example:

(module geometry
  (export area circumference)
  (import std.math)
  (begin
    (defun area (r) (* pi (* r r)))
    (defun circumference (r) (* 2 pi r))))

Module Linker Phases

The ModuleLinker resolves inter-module dependencies in two passes:

flowchart LR subgraph "Pass 1: Index" SCAN["Scan all (module …) forms"] SCAN --> DEF["Collect define names"] SCAN --> EXP["Collect export names"] SCAN --> IMP["Queue import specs"] end subgraph "Pass 2: Link" RES["Resolve imports"] RES --> FILT["Apply only / except / rename"] FILT --> VIS["Populate visible set\n(defined ∪ imported)"] end SCAN --> RES

Pass 1 — index_modules()

For each (module name ...) form:

  1. Create a ModuleTable entry with the module name
  2. Scan the body for define / defun forms ? populate defined
  3. Scan (export …) ? populate exports
  4. Queue (import …) clauses as PendingImports

Errors detected: DuplicateModule

For each queued PendingImport:

  1. Look up the source module’s exports set
  2. Apply the import filter:
FilterEffect
(import mod)Import all exported names
(import (only mod a b))Import only a and b
(import (except mod x))Import all except x
(import (rename mod (old new)))Import old as new
  1. Check for conflicts with already-visible names
  2. Add resolved names to the target module’s visible set
  3. Record provenance in import_origins for diagnostics

Errors detected: UnknownModule, CircularDependency, ConflictingImport, NameNotExported, ExportOfUnknownName


Incremental Execution (REPL)

The Driver supports incremental execution for the REPL:

sequenceDiagram participant User participant Driver participant Linker participant SA as SemanticAnalyzer participant VM User->>Driver: run_source("(module a ...)") Driver->>Driver: Lex + Parse + Expand Driver->>Driver: Append to accumulated_forms_ Driver->>Linker: index_modules(ALL accumulated forms) Driver->>Linker: link() Driver->>SA: analyze_all(ALL forms) Driver->>VM: Execute only NEW modules Driver-->>User: result User->>Driver: run_source("(module b (import a) ...)") Driver->>Driver: Lex + Parse + Expand Driver->>Driver: Append to accumulated_forms_ Driver->>Linker: index_modules(ALL accumulated forms) Note over Linker: Re-indexes everything<br/>(linker is non-incremental) Driver->>Linker: link() Driver->>SA: analyze_all(ALL forms) Driver->>VM: Execute only module b (a already executed) Driver-->>User: result

Key properties:


Stdlib Loading

Eta does not auto-load a prelude module. Import stdlib modules explicitly in each module or REPL submission.


Standard Library Reference

All standard library modules are defined in the stdlib/std/ directory. Use explicit imports for each module you depend on:

(import std.core)
(import std.math)
(import std.io)

std.core — Core Combinators & Predicates

(import std.core)
FunctionSignatureDescription
atom?(x) ? boolTrue if x is not a pair
void() ? '()Returns the empty list
identity(x) ? xIdentity function
compose(f g) ? (λ (x) (f (g x)))Function composition
flip(f) ? (λ (a b) (f b a))Swap arguments
constantly(v) ? (λ args v)Always returns v
negate(pred) ? (λ (x) (not (pred x)))Negate a predicate
cadr(xs) ? elementSecond element
caddr(xs) ? elementThird element
caar, cdar, caddar(xs) ? elementNested accessors
last(xs) ? elementLast element of a list
list?(x) ? boolTrue if x is a proper list
iota(count [start [step]]) ? listGenerate a sequence
assoc-ref(key alist) ? value | #fAssociation list lookup

std.math — Mathematical Functions

(import std.math)
BindingTypeDescription
piconstant3.141592653589793
econstant2.718281828459045
square(x) ? x→Square
cube(x) ? x→Cube
even?(n) ? boolEven predicate
odd?(n) ? boolOdd predicate
sign(x) ? -1 | 0 | 1Sign function
clamp(x lo hi) ? numberClamp to range
quotient(a b) ? numberInteger quotient
gcd(a b) ? numberGreatest common divisor
lcm(a b) ? numberLeast common multiple
expt(base exp) ? numberExponentiation (fast power)
sum(xs) ? numberSum of a list
product(xs) ? numberProduct of a list

std.aad — AD Helpers and Gradient Checks

(import std.aad)
FunctionSignatureDescription
grad(f vals) ? (list primal grad-vector)Run tape-based reverse-mode AD on scalar f
ad-abs(x) ? numberPolicy-aware absolute value
ad-max / ad-min(a b ...) ? numberPolicy-aware piecewise max/min
ad-relu(x) ? numbermax(0, x) built on AD-safe primitives
ad-clamp(x lo hi) ? numberPolicy-aware clamp
softplus(x beta) ? numberSmooth approximation to max(0, x)
smooth-abs(x epsilon) ? numberSmooth absolute value (epsilon required)
smooth-clamp(x lo hi beta) ? numberSmooth clamp approximation
check-grad(f vals [rtol [atol [step-scale]]]) ? boolCompare AAD gradient vs finite differences
check-grad-report(f vals [rtol [atol [step-scale]]]) ? vectorDetailed gradient-check report
with-checkpoint(thunk) ? resultCheckpoint API surface for AD blocks

std.io — Input/Output Utilities

(import std.io)
FunctionSignatureDescription
print(x)Display x
println(x)Display x followed by newline
eprintln(x)Print to stderr
display-to-string(x) ? stringRender value to string via string port
read-line([port]) ? string | #fRead a line (returns #f at EOF)
with-output-to-port(port thunk) ? resultRedirect stdout for thunk
with-input-from-port(port thunk) ? resultRedirect stdin for thunk
with-error-to-port(port thunk) ? resultRedirect stderr for thunk

std.collections — Higher-Order List & Vector Operations

(import std.collections)
FunctionSignatureDescription
map*(f xs) ? listMap (single-list)
map2(f xs ys) ? listPairwise map over two lists (truncates to shorter list)
zip-with(f xs ys) ? listAlias for map2
map-indexed(f xs) ? listMap with zero-based index (calls f with i and x)
filter(pred xs) ? listKeep elements matching pred
foldl(f acc xs) ? valueLeft fold
foldr(f init xs) ? valueRight fold
reduce(f xs) ? valueFold without initial accumulator
any?(pred xs) ? boolTrue if any element matches
every?(pred xs) ? boolTrue if all elements match
count(pred xs) ? numberCount matching elements
sum-by(f xs) ? numberSum transformed elements
zip(xs ys) ? listZip two lists into pairs
pairwise(xs) ? listAdjacent element pairs as dotted pairs
take(n xs) ? listFirst n elements
drop(n xs) ? listSkip first n elements
flatten(xss) ? listFlatten one level of nesting
range(start end) ? listInteger range [start, end)
sort(less? xs) ? listMerge sort with custom comparator
vector-map(f v) ? vectorMap over a vector
vector-for-each(f v)Side-effecting vector traversal
vector-foldl(f acc v) ? valueLeft fold over a vector
vector-foldr(f init v) ? valueRight fold over a vector
vector->list(v) ? listConvert vector to list
list->vector(xs) ? vectorConvert list to vector

std.hashmap — Hash Map Helpers

(import std.hashmap)

Runtime primitives:

FunctionSignatureDescription
hash-map(k1 v1 k2 v2 ...) -> mapConstruct a map from key/value pairs
make-hash-map() -> mapEmpty hash map
hash-map?(x) -> boolHash map predicate
hash-map-ref(m k [default]) -> valueLookup with optional default
hash-map-assoc(m k v) -> mapReturn a map with k bound to v
hash-map-dissoc(m k) -> mapReturn a map without k
hash-map-keys(m) -> listKeys as a list
hash-map-values(m) -> listValues as a list
hash-map-size(m) -> intNumber of entries
hash-map->list(m) -> listAssociation-list form ((k . v) ...)
list->hash-map(xs) -> mapBuild from alist or flat key/value list
hash-map-fold(f init m) -> valueFold with (f acc k v)
hash(x) -> intGeneric hash function

Convenience wrappers:

hash-map-empty?, hash-map-contains?, hash-map-update, hash-map-update-with-default, hash-map-merge, hash-map-merge-with, hash-map-map, hash-map-filter, hash-map->alist, alist->hash-map.


std.hashset — Hash Set Helpers

(import std.hashset)

Runtime primitives:

FunctionSignatureDescription
make-hash-set() -> setEmpty hash set
hash-set(x1 x2 ...) -> setConstruct a set from values
hash-set?(x) -> boolHash set predicate
hash-set-add(s x) -> setAdd an element
hash-set-remove(s x) -> setRemove an element
hash-set-contains?(s x) -> boolMembership check
hash-set-union(a b) -> setUnion
hash-set-intersect(a b) -> setIntersection
hash-set-diff(a b) -> setDifference a \ b
hash-set->list(s) -> listSet elements as a list
list->hash-set(xs) -> setBuild from list

Convenience wrappers:

hash-set-empty?, hash-set-size, hash-set-subset?, hash-set-equal?.


std.atom - Atomic Mutable References (opt-in)

(import std.atom)

Provides single-cell mutable references with CAS semantics.

FunctionSignatureDescription
atom:new(value) -> atomCreate a new atom.
atom:atom?(x) -> boolAtom predicate.
atom:deref(a) -> valueRead current value.
atom:reset!(a value) -> valueReplace current value and return it.
atom:swap!(a fn arg ...) -> valueCompute and install a new value via CAS retry.
atom:compare-and-set!(a old new) -> boolCAS from old to new using raw LispVal equality.

Alias exports are also provided for explicit opt-in imports: atom, atom?, deref, reset!, swap!, compare-and-set!.

For full details and collision guidance with std.core:atom?, see Atom.


std.regex — Regular Expressions

(import std.regex)

Regex helpers backed by C++ std::regex (ECMAScript syntax). The API accepts either compiled regex handles or string patterns.

FunctionSignatureDescription
regex:compile(pattern . flags) -> regexCompile a reusable regex object
regex:match?(regex-or-pattern input) -> boolFull-string match
regex:search(regex-or-pattern input [start]) -> match-or-#fFirst match with offsets/captures
regex:find-all(regex-or-pattern input) -> listAll matches
regex:replace(regex-or-pattern input replacement) -> stringReplacement string form ($1, $<name>, etc.)
regex:replace-fn(regex-or-pattern input fn) -> stringCallback replacement form
regex:split(regex-or-pattern input) -> vectorRegex delimiter split
regex:quote(s) -> stringEscape regex metacharacters
regex:match-groups-hash(match) -> hash-mapNamed capture groups as a hash map of name -> (start . end)

For the full reference and performance notes, see Regex.


std.test — Lightweight Test Framework

(import std.test)

Uses define-record-type for test-case, test-group, test-result, group-result, and test-summary.

FunctionDescription
make-test(name thunk) — create a test case
make-group(name children) — create a test group
run(node) ? result — run a test or group
summary(result) ? test-summary — count pass/fail
print-summary(summary) — display totals
assert-true(x [msg]) — assert truthy
assert-false(x [msg]) — assert falsy
assert-equal(expected actual [msg]) — assert equality
assert-not-equal(a b [msg]) — assert inequality
assert-approx-equal(expected actual tol [msg]) → assert numeric closeness within tol
print-tap(result) — emit TAP-formatted output for CI consumers
print-junit(result [port]) — emit JUnit XML for CI consumers

Example:

(module my-tests
  (import std.test)
  (import std.math)
  (import std.io)
  (begin
    (define suite
      (make-group "math"
        (list
          (make-test "square"
            (lambda () (assert-equal 25 (square 5))))
          (make-test "gcd"
            (lambda () (assert-equal 6 (gcd 12 18)))))))

    (let ((result (run suite)))
      (print-summary (summary result)))))

Output:

2 tests, 2 passed, 0 failed


std.logic — Relational / miniKanren-style Programming

(import std.logic)

Provides logic variables, unification, search combinators, and a miniKanren-flavoured surface (fresh, conde, conj, disj, run*, run-n, run1, ==, ==o, succeedo, failo, copy-term*, naf, succeeds?, findall, membero, condu, conda, onceo, logic-throw, logic-catch).

Full documentation: Logic Programming


std.clp — Constraint Logic Programming over Integers / Finite Domains

(import std.clp)

Domain constructors ((z lo hi), (fd v1 v2 ...)), constraint posting (clp:= clp:+ clp:plus-offset clp:abs clp:* clp:sum clp:scalar-product clp:element clp:<= clp:>= clp:<>), clp:all-different, search (clp:solve, clp:labeling), and optimisation (clp:minimize, clp:maximize). Shares the unified trail and the 'clp.prop async propagation queue with std.clpb and std.clpr.

Full documentation: Constraint Logic Programming (Z/FD)


std.clpb — Boolean Constraint Logic (opt-in)

(import std.clpb)

Boolean variables and constraints (clp:boolean, clp:and, clp:or, clp:xor, clp:imp, clp:eq, clp:not, clp:card) plus search and queries (clp:labeling-b, clp:sat?, clp:taut?). Requires explicit import.

Full documentation: Boolean Constraints (CLP(B))


std.clpr — Real-Interval Constraint Logic (opt-in)

(import std.clpr)

Real-domain constructors and accessors, linear arithmetic (clp:r+, clp:r-, clp:r*scalar), constraint posting (clp:r=, clp:r<=, clp:r<, clp:r>=, clp:r>), simplex/QP optimisation (clp:r-minimize, clp:r-maximize, clp:rq-minimize, clp:rq-maximize), and queries (clp:r-bounds, clp:r-feasible?). Requires explicit import.


std.db — Procedural Datalog over Fact Tables

(import std.db)

Defines persistent relations as defrel, asserts/retracts ground facts (assert, retract, retract-all), queries via call-rel / call-rel?, builds per-argument indexes (index-rel!), and tabulates recursive rules (tabled).

Full documentation: Datalog Database


std.causal — DAGs, Do-Calculus, and Causal Estimation

(import std.causal)

DAG utilities (dag:nodes, dag:parents, …), do-calculus identification (do:identify, do:identify-details, observed variants), and numeric estimators (do:estimate-effect, do:conditional-mean, do:marginal-prob).

Full documentation: Causal Inference

ADMG-specific helpers (districts and latent projection) are in a separate submodule:

(import std.causal.admg)

Generalized adjustment/front-door/IV helpers are available in:

(import std.causal.adjustment)

Estimation backends (g-formula, IPW, AIPW, TMLE, bootstrap CI, sensitivity metrics) are available in:

(import std.causal.estimate)

Graph rendering helpers (DOT, Mermaid, LaTeX, literal validation) are available in:

(import std.causal.render)

std.stats — Statistics & Linear Models

(import std.stats)

Descriptive statistics, distribution quantiles, bivariate measures, OLS (returns a %ols-result record with backward-compatible nine-element list accessors), multivariate regression, and column-wise operations over lists, vectors, or fact-table columns. Eigen-backed.

Full documentation: Statistics


std.time - Wall-Clock and Monotonic Time

(import std.time)

Time helpers for wall-clock timestamps, monotonic elapsed measurement, sleep/delay, UTC/local calendar breakdown, and ISO-8601 formatting.

FunctionSignatureDescription
time:now-ms() -> intCurrent Unix epoch in milliseconds
time:now-us() -> intCurrent Unix epoch in microseconds
time:now-ns() -> intCurrent Unix epoch in nanoseconds
time:monotonic-ms() -> intMonotonic milliseconds (origin unspecified)
time:sleep-ms(ms) -> '()Sleep current thread for ms milliseconds
time:utc-parts(epoch-ms) -> alistDate/time parts with offset-minutes = 0
time:local-parts(epoch-ms) -> alistLocal date/time parts with timezone offset
time:format-iso8601-utc(epoch-ms) -> stringYYYY-MM-DDTHH:MM:SSZ
time:format-iso8601-local(epoch-ms) -> stringYYYY-MM-DDTHH:MM:SS+/-HH:MM
time:elapsed-ms(start end) -> intNon-negative monotonic delta

Example:

(let ((t0 (time:monotonic-ms)))
  (time:sleep-ms 25)
  (println (time:elapsed-ms t0 (time:monotonic-ms))))

std.fs — Filesystem and Path Primitives

(import std.fs)

Path manipulation, directory enumeration, file metadata, and temp-file allocation backed by std::filesystem. Requires explicit import.

FunctionSignatureDescription
fs:file-exists?(path) -> boolPath resolves on disk
fs:directory?(path) -> boolPath is a directory
fs:delete-file(path) -> '()Remove a regular file
fs:make-directory(path) -> '()Create a directory (idempotent)
fs:list-directory(path) -> listSorted entry names
fs:path-join(seg ...) -> stringVariadic path build
fs:path-split(path) -> listInverse of fs:path-join
fs:path-normalize(path) -> stringLexical canonicalisation
fs:temp-file() -> stringAllocate a unique temp-file path
fs:temp-directory() -> stringAllocate a unique temp dir
fs:file-modification-time(path) -> intmtime in epoch ms
fs:file-size(path) -> intSize in bytes

Full documentation: Filesystem


std.os — Process / Environment Primitives

(import std.os)

Environment variables, command-line arguments, current working directory, and process exit. Requires explicit import.

FunctionSignatureDescription
os:getenv(name) -> string | #fLookup, #f if unset
os:setenv!(name value) -> '()Mutate process environment
os:unsetenv!(name) -> '()Idempotent unset
os:environment-variables() -> alistSorted ("KEY" . "value") pairs
os:command-line-arguments() -> listStrings passed after the script
os:exit([code]) -> neverTerminate the process
os:current-directory() -> stringWorking directory
os:change-directory!(path) -> '()chdir equivalent

Full documentation: OS Primitives


std.process - Subprocess Execution (opt-in)

(import std.process)

Blocking and non-blocking subprocess support with captured stdio and pipe-backed ports that integrate with existing read-u8, write-u8, and close-port workflows.

FunctionSignatureDescription
process:run(program args [opts]) -> (status stdout stderr)Blocking run with capture/inherit/null stream options
process:spawn(program args [opts]) -> handleNon-blocking spawn returning a process handle
process:wait(handle [timeout-ms]) -> int or #fWait for completion (#f on timeout)
process:kill / process:terminate(handle) -> boolHard/soft termination
process:pid / process:alive? / process:exit-code(handle) -> ...Lifecycle state accessors
process:stdin-port / process:stdout-port / process:stderr-port(handle) -> port or #fChild stdio port access
process:run-string(program args [opts]) -> stdoutConvenience accessor for captured stdout

Full documentation: Subprocesses


std.freeze - Coroutine-Style Goal Suspension (opt-in)

(import std.freeze)

Adds freeze (suspend a goal until a logic variable is bound) and dif (disequality between terms) on top of the attributed-variable substrate. Requires explicit import.

Full documentation: Freeze & Dif


std.supervisor — Erlang-Style Process Supervision (opt-in)

(import std.supervisor)

one-for-one and one-for-all supervisors built on top of the nng actor primitives (spawn, monitor, nng-poll, recv!). Requires explicit import.

Full documentation: Supervisors


std.fact_table — Columnar Fact Tables

(import std.fact_table)

An in-memory, column-oriented store of fixed-arity rows with optional per-column hash indexes for O(1) equality lookups.

CategoryKey Functions
Constructionmake-fact-table, fact-table?
Mutationfact-table-insert!, fact-table-build-index!
Queryfact-table-query, fact-table-ref, fact-table-row-count, fact-table-row
Iterationfact-table-for-each, fact-table-filter, fact-table-fold
Aggregationfact-table-group-count, fact-table-group-sum, fact-table-group-by, fact-table-partition
CSV Bridgefact-table-load-csv, fact-table-save-csv

Full documentation: Fact Tables


std.csv — Native CSV Reader/Writer

(import std.csv)

Native CSV API backed by vincentlaucsb/csv-parser.

CategoryKey Functions
Readercsv:open-reader, csv:reader-from-string, csv:columns, csv:read-row, csv:read-record, csv:read-typed-row, csv:close
Writercsv:open-writer, csv:write-row, csv:write-record, csv:flush, csv:save-file
Streamingcsv:fold, csv:for-each, csv:collect, csv:load-file

Full documentation: CSV


std.json — Native JSON Reader/Writer

(import std.json)

RFC 8259 JSON codec implemented in-tree (eta/core/src/eta/util/json.h, no third-party dependency). Objects decode to hash maps, arrays to vectors, numbers default to flonums (with an opt-in 'keep-integers-exact? flag for integer fidelity). Requires explicit import.

FunctionSignatureDescription
json:read(port [opts ...]) -> valueRead one JSON document from an input port
json:read-string(string [opts ...]) -> valueParse a JSON string
json:write(value [port]) -> '()Write JSON to a port (default: current-output-port)
json:write-string(value) -> stringSerialise to a string

Full documentation: JSON


Prelude Status

std.prelude is not part of the standard library contract. Import modules explicitly.


std.torch — libtorch Neural Network Bindings

(import std.torch)
CategoryKey Functions
Tensor creationtensor, ones, zeros, randn, manual-seed, arange, linspace, from-list
Arithmetict+, t-, t*, t/, matmul, dot
Linear algebra/samplingcholesky, mvnormal
Unary opsneg, tabs, texp, tlog, tsqrt, relu, sigmoid, ttanh, softmax
Shapeshape, reshape, transpose, squeeze, unsqueeze, cat
Reductionstsum, mean, tmax, tmin, argmax, argmin
Conversionitem, to-list, numel
Autogradrequires-grad!, requires-grad?, detach, backward, grad, zero-grad!
NN layerslinear, sequential, relu-layer, sigmoid-layer, dropout, forward, parameters, train!, eval!
Loss functionsmse-loss, l1-loss, cross-entropy-loss
Optimizerssgd, adam, step!, optim-zero-grad!
Devicegpu-available?, gpu-count, device, to-device, to-gpu, to-cpu, nn-to-device
Helperstrain-step! — one-call training step (zero-grad ? forward ? loss ? backward ? step)

Full documentation: Neural Networks with libtorch


std.net — Networking & Message Passing

(import std.net)

nng is the networking layer; the low-level primitives (nng-socket, send!, recv!, spawn, etc.) are registered as global builtins. std.net adds high-level Erlang-inspired patterns on top.

High-level helpers

FunctionSignatureDescription
with-socket(with-socket type thunk)Create a socket, run (thunk sock), close via dynamic-wind — safe even on exceptions
request-reply(request-reply endpoint message)Open a REQ socket, dial, send, receive exactly one reply, close
worker-pool(worker-pool module-path tasks)Spawn one child per task, dispatch, collect results in order, clean up
pub-sub(pub-sub endpoint topics handler)Connect a SUB socket, subscribe to topics, call handler on each message
survey(survey endpoint question timeout-ms)Open a SURVEYOR socket, broadcast question, collect all responses before deadline

Low-level nng builtins (globally available)

PrimitiveSignatureDescription
nng-socket(nng-socket type-sym)Create a socket → 'pair, 'req, 'rep, 'pub, 'sub, 'push, 'pull, 'surveyor, 'respondent, 'bus
nng-listen(nng-listen sock endpoint)Bind and listen on an endpoint
nng-dial(nng-dial sock endpoint)Connect to an endpoint (auto-reconnects)
nng-close(nng-close sock)Close the socket (idempotent; also called by GC)
nng-socket?(nng-socket? x)Socket predicate
send!(send! sock value [flag])Serialize and send; flags: 'text, 'noblock, 'wait
recv!(recv! sock [flag])Receive and deserialize; returns #f on timeout; flags: 'noblock, 'wait
nng-poll(nng-poll items timeout-ms)Poll multiple sockets; returns list of ready sockets
nng-subscribe(nng-subscribe sock topic)Set SUB topic filter (byte prefix)
nng-set-option(nng-set-option sock option value)Set socket option ('recv-timeout, 'send-timeout, 'survey-time, …)

Actor model builtins (globally available)

PrimitiveSignatureDescription
spawn(spawn module-path [endpoint])Spawn a child etai process; returns parent-side PAIR socket
spawn-wait(spawn-wait sock)Block until the child process exits; return exit code
spawn-kill(spawn-kill sock)Forcibly terminate the child process
spawn-thread(spawn-thread thunk)Run a 0-arg closure (with captured upvalues) in a fresh in-process VM thread; returns the parent-side PAIR socket
spawn-thread-with(spawn-thread-with proc args)In-process variant for a named procedure plus argument list
thread-join(thread-join sock)Wait for an in-process actor thread to finish
thread-alive?(thread-alive? sock)Non-blocking thread liveness check
monitor(monitor sock)Receive a (down ...) message when the peer (process or thread) exits
current-mailbox(current-mailbox)Inside a spawned child or thread: return the PAIR socket to the parent

Usage examples

;; Safe socket management
(with-socket 'req
  (lambda (sock)
    (nng-dial sock "tcp://localhost:5555")
    (send! sock '(compute 42))
    (recv! sock 'wait)))

;; One-shot synchronous RPC
(request-reply "tcp://localhost:5555" '(compute 42))

;; Parallel fan-out
(worker-pool "worker.eta" '(1 2 3 4 5))

;; Subscribe to a topic stream
(pub-sub "tcp://localhost:5556"
         '("prices" "alerts")
         (lambda (msg) (println msg)))

;; Scatter-gather query
(survey "tcp://*:5557" '(status?) 1000)

Full documentation: Networking Primitives · Message Passing & Actors · Examples


Builtin Primitives vs. Standard Library

There are two layers of “standard” functionality:

LayerDefined inMechanism
BuiltinsC++ (core_primitives.h, io_primitives.h, port_primitives.h)Registered as Primitive heap objects in fixed global slots
Standard LibraryEta (std/*.eta)Regular Eta functions defined in modules

Builtins like +, cons, display are always available (they occupy global slots 0..N−1). The standard library modules build on top of builtins to provide higher-level abstractions like foldl, sort, and read-line.


LSP Integration

File: lsp_server.h

The eta_lsp executable implements the Language Server Protocol over JSON-RPC (stdio). It creates a Driver internally and runs the compilation pipeline on each textDocument/didOpen and didChange event, publishing diagnostics back to the editor.

Supported LSP features:

VS Code Extension

The editors/vscode/ directory contains a VS Code extension that provides:

Install via the build script or manually with vsce package.