cljrs-stdlib
Built-in standard library namespaces for clojurust, distributed as embedded source + native Rust helpers.
Status
Phase 8-ext. Provides clojure.string, clojure.set, and clojure.test as
lazily-loaded built-ins; no filesystem dependency at runtime.
Purpose
Clojurust has no classpath or JAR mechanism. This crate solves the distribution
problem by embedding .cljrs source files via include_str! and registering
them in GlobalEnv::builtin_sources so that (require '[clojure.string :as str])
works out of the box in any binary that calls cljrs_stdlib::standard_env().
File layout
src/
lib.rs Public API: register(), the standard_env* constructors,
and the embedded-source include_str! table
string.rs Native Rust implementations for clojure.string
set.rs Native Rust implementations for clojure.set
io.rs Native Rust implementations for clojure.rust.io
(IoReader/IoWriter/StringReader); not built for wasm32
edn.rs Native Rust implementations for clojure.edn; not built for wasm32
clojure/
string.cljrs Clojure source for clojure.string (ns decl; natives pre-registered)
set.cljrs Clojure source for clojure.set (ns decl; natives pre-registered)
template.cljrs Pure Clojure implementation of clojure.template
test.cljrs Pure Clojure implementation of clojure.test
walk.cljrs Pure Clojure implementation of clojure.walk
data.cljrs Pure Clojure implementation of clojure.data
zip.cljrs Pure Clojure implementation of clojure.zip
edn.cljrs Clojure source for clojure.edn (ns decl; natives pre-registered)
rust/
io.cljrs Clojure source for clojure.rust.io (ns decl; natives pre-registered)
spec/
alpha.cljrs Pure Clojure implementation of clojure.spec.alpha (core spec engine)
test/
alpha.cljrs Pure Clojure implementation of clojure.spec.test.alpha (instrument/unstrument)
gen/
alpha.cljrs clojure.spec.gen.alpha stub — every fn throws (no generator engine)
There is no build script. Lowering to IR happens at run time in pure Rust
(cljrs_ir::lower); this crate ships source, not a prebuilt IR bundle.
Public API
Entry points
/// Register all built-in stdlib namespaces into an existing GlobalEnv.
;
/// Create a GlobalEnv with bootstrap + stdlib registered (lazy loading),
/// GC configured from the environment, and IR lowering enabled.
/// Not built for wasm32.
;
/// Like standard_env() but without the IR lowering hook — used by the AOT test
/// harness, where lowering test-namespace functions would fill the global IR
/// cache with entries nothing ever evicts. Not built for wasm32.
;
/// Like standard_env() but also sets user source paths for require.
/// Not built for wasm32.
;
/// Like standard_env_with_paths() but also overrides the GC configuration.
/// Not built for wasm32.
;
Each native module exposes its own registrar, called by register():
register;
register;
register; // wasm32: absent
register; // wasm32: absent
io is the only one of these that is pub at the crate root; it also exports
the IoReader, IoWriter, and StringReader native object types.
Namespaces provided
| Namespace | Implementation | Notes |
|---|---|---|
clojure.string |
string.rs + clojure/string.cljrs |
Native Rust, loaded lazily |
clojure.set |
set.rs + clojure/set.cljrs |
Native Rust, loaded lazily |
clojure.test |
clojure/test.cljrs |
Pure Clojure, loaded lazily |
clojure.spec.alpha |
clojure/spec/alpha.cljrs |
Pure Clojure, loaded lazily |
clojure.spec.test.alpha |
clojure/spec/test/alpha.cljrs |
Pure Clojure, loaded lazily |
clojure.spec.gen.alpha |
clojure/spec/gen/alpha.cljrs |
Pure Clojure, loaded lazily; every fn throws (no generator engine) |
clojure.string functions
upper-case, lower-case, capitalize, trim, triml, trimr,
trim-newline, blank?, starts-with?, ends-with?, includes?,
replace, replace-first, split, split-lines, join,
index-of, last-index-of
replace and replace-first accept either a string or a regex pattern
(#"...") as the match argument. When the match is a pattern, replace
replaces all occurrences and replace-first replaces only the first.
clojure.set functions
union, intersection, difference, subset?, superset?,
select, map-invert
clojure.spec.alpha functions and macros
A from-scratch, spec-compatible-in-spirit implementation of the core spec
engine: predicate/set/keyword specs, and/or composition, keys/merge,
the derivative-based regex engine (cat/alt/*/+/?/&), collection
specs, and fn-specs (fdef/fspec).
Macros: def, spec, and, or, keys, merge, cat, alt, *, +,
?, &, every, coll-of, every-kv, map-of, tuple, nilable,
multi-spec, conformer, nonconforming, fspec, fdef, assert
Functions: registry, get-spec, invalid, invalid?, spec-name,
spec?, conform, unform, valid?, form, describe, explain-data,
explain, explain-str, explain-out, regex?, int-in, double-in,
inst-in (throws — see deviations), check-asserts?, check-asserts,
with-gen, gen, exercise, exercise-fn (the last three throw — see
deviations)
Deviations from JVM clojure.spec.alpha
- No generators:
s/gen,s/exercise,s/exercise-fn, andstest/check/stest/check-fnall throw a clearex-infoinstead of running test.check.s/with-genstores the generator fn without ever invoking it. s/formands/describeshow forms exactly as written (unqualified) — they do not auto-qualify bare symbols toclojure.corethe way upstream does.multi-specunform re-dispatches by calling the multimethod on the conformed value rather than applying JVM spec'sretagmechanism.check-assertstakes effect immediately (read at assert-expansion time), not just at compile time as on the JVM.inst-inalways throws — this runtime has noinst?/date value type to bound.- Users must
:requirethe namespace with an alias (:as s, the universal convention anyway).:refering names likeand,or, ordefcollides with clojurust's special forms, and:refer-clojure :excludeis a no-op in this runtime, so it cannot be used to work around the collision.
clojure.spec.test.alpha functions and macros
Macros: with-instrument-disabled
Functions: instrument, unstrument, instrumentable-syms, check (throws
— see deviations), check-fn (throws — see deviations)
instrument wraps a var's root fn so every call conforms its argument list
against the fn's fdef'd :args spec before delegating to the original fn;
only :args is checked (never :ret/:fn, matching upstream). unstrument
restores the original fn. Both are idempotent.
clojure.spec.gen.alpha functions
generate, sample, gen-for-pred, choose, such-that, fmap, one-of,
return, elements, int, string, keyword, boolean, double,
simple-type, any
This namespace has no generator engine (no test.check port): every function
throws a clear ex-info explaining that generators are not implemented. It
exists purely so that idiomatic specs which (:require [clojure.spec.gen.alpha :as gen]) load cleanly. As in upstream, several names (int, string,
keyword, boolean, double) intentionally shadow clojure.core.
Dependency notes
cljrs-stdlibdepends oncljrs-eval(forGlobalEnv,standard_env_minimal)cljrs-evaldoes not depend oncljrs-stdlib(no circular dep)- The
cljrsbinary depends on both; usecljrs_stdlib::standard_env()instead ofcljrs_eval::standard_env()so that stdlib namespaces are available