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 — Actor Supervisor Compatibility Shim (opt-in)

(import std.supervisor)

Compatibility module that re-exports std.actor.supervisor. New actor code should import std.actor.supervisor directly for one-for-one, one-for-all, rest-for-one, child specs, and restart-intensity controls. 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.actor — PID-based Actors

(import std.actor)

std.actor is the primary local concurrency API.

FunctionSignatureDescription
self(self)Return current actor PID
spawn(spawn thunk)Spawn one local actor
send(send pid payload)Send one message to PID or registered name
receive(receive cases [timeout-ms [timeout-thunk]])Selective receive with optional timeout
receive-after(receive-after timeout-ms)Receive one message or #f on timeout
monitor(monitor pid)Register process monitor and return monitor ref
demonitor(demonitor ref [flush?])Remove monitor; optional flush removes queued DOWN
link / unlink(link pid) / (unlink pid)Link or unlink actor exits
trap-exit!(trap-exit! enabled?)Toggle trapped linked exits as mailbox messages
register / whereis(register name pid) / (whereis name)Local name registry
process-info(process-info pid [key])Process metadata/introspection

Related modules: std.actor.supervisor, std.actor.gen_server, and std.actor.node.


std.net — Networking Transport

(import std.net)

std.net is the explicit NNG transport layer. Use it for socket-level communication patterns and endpoint management.

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)Compatibility helper over socket-based child workers
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, …)

Legacy process-spawn socket helpers (compatibility)

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)Child-side PAIR socket for legacy socket-mailbox workflows

Transport 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))

;; 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: std.actor · std.actor.node · std.net


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.