Introduction
clojurust is a Rust-hosted dialect of the Clojure programming language. It reads
and executes .cljrs and .cljc source files, provides an interactive REPL, and
can AOT-compile programs to standalone native binaries.
Goals
- Interpreter — read and execute
.cljrs(native) and.cljc(cross-platform) source files. - Reader conditionals —
.cljcfiles use#?(:rust ... :clj ... :default ...)to branch on platform; the platform key for clojurust is:rust. - Rust interop — Clojure code can call Rust functions through a defined set of conventions and type-marshalling primitives.
- Garbage collector — a tracing GC manages all Clojure values; an optional region-based allocator is available for allocation-heavy code paths.
- AOT compilation —
cljrs compileproduces a standalone native binary via Cranelift.
Source file extensions
| Extension | Meaning |
|---|---|
.cljrs | Native clojurust source. Always evaluated under the :rust platform. |
.cljc | Cross-platform source. Reader conditionals select the active branch; clojurust evaluates :rust branches. |
Quick start
cljrs run hello.cljrs
cljrs repl
cljrs eval '(+ 1 2)'
cljrs compile app.cljrs -o app
cljrs test --src-path test
Detailed documentation for each subcommand is in the CLI chapter.
Command-line tool
cljrs is the command-line entry point for clojurust. It provides subcommands
for running files, starting a REPL, evaluating expressions, compiling to native
binaries, running tests, and managing dependencies.
cljrs [GLOBAL OPTIONS] <SUBCOMMAND> [SUBCOMMAND OPTIONS]
Subcommands
| Subcommand | Description |
|---|---|
run | Interpret a .cljrs or .cljc source file |
repl | Start an interactive REPL |
eval | Evaluate a single expression and print the result |
compile | AOT-compile a source file to a native binary |
test | Run clojure.test namespaces |
deps | Manage project dependencies declared in cljrs.edn |
ir-viz | Render the optimised IR for a source file to HTML |
Global options
These options are accepted by every subcommand.
--stack-size-mb <MB>
Set the main thread’s stack size in megabytes. Defaults to 64 MB. Increase this value if you encounter stack overflows in deeply recursive code.
cljrs --stack-size-mb 128 run my-program.cljrs
--debug
Enable debug-level logging. Prints internal diagnostics to stderr.
--trace
Enable trace-level logging (implies --debug). Much more verbose than --debug.
-X <LEVEL:FEATURES>
Feature-scoped logging. Enables logging at LEVEL for the named comma-separated
FEATURES only.
cljrs -X debug:gc,reader run my-program.cljrs
cljrs -X trace:jit run my-program.cljrs
Available levels: debug, trace.
Available features: gc, reader, jit, and others.
--gc-stats [FILE]
Print garbage-collector statistics on exit. Pass a file path to write the report there; omit the path to write to stdout.
Only honoured by run, eval, and test.
cljrs --gc-stats run my-program.cljrs # stats to stdout
cljrs --gc-stats gc.log run my-program.cljrs # stats to file
--verify-commit-signatures
Require valid GPG or SSH signatures on every versioned commit before executing
historical code. Off by default. Can also be enabled per-project in cljrs.edn
via :verify-commit-signatures true.
Project configuration: cljrs.edn
When any of run, repl, compile, or test starts, clojurust walks up the
directory tree from the current working directory and loads the nearest
cljrs.edn it finds. The :paths declared in that file are appended to the
source-path list (CLI --src-path values come first).
See deps for the full format of cljrs.edn.
cljrs run
Interpret a .cljrs or .cljc source file.
cljrs run [OPTIONS] <FILE>
All top-level forms in FILE are evaluated in order. The return value of the
last form is discarded; side effects (output, file writes, etc.) are the
intended mechanism for a run program to produce observable results.
Arguments
| Argument | Description |
|---|---|
<FILE> | Path to the source file (.cljrs or .cljc) |
Options
--src-path <DIR>
Add DIR to the list of directories searched when resolving require. May be
repeated to add multiple directories.
cljrs run --src-path src --src-path lib my-program.cljrs
Paths declared in :paths of the nearest cljrs.edn are appended automatically
after CLI paths.
--gc-soft-limit-mb <MB>
Soft memory limit for the GC in megabytes. When live heap exceeds this value, a collection is triggered at the next safepoint.
--gc-hard-limit-mb <MB>
Hard memory limit for the GC in megabytes. When live heap exceeds this value, a collection is forced immediately.
Examples
# Run a file in the current directory
cljrs run hello.cljrs
# Run with a source path for namespace resolution
cljrs run --src-path src src/myapp/core.cljrs
# Run and write GC stats to stderr on exit
cljrs --gc-stats run my-program.cljrs
cljrs repl
Start an interactive read–eval–print loop.
cljrs repl [OPTIONS]
The REPL reads one expression at a time, evaluates it, and prints the result. Multi-line input is supported: the REPL continues reading until all open brackets are closed before evaluating.
Type :quit or press Ctrl-D to exit.
Options
--src-path <DIR>
Add DIR to the source-path list for require. May be repeated.
--gc-soft-limit-mb <MB> / --gc-hard-limit-mb <MB>
GC memory limits. See run for details.
REPL behaviour
- The initial namespace is
user. - The standard library (
clojure.coreand friends) is pre-loaded. *1,*2,*3hold the last three non-nil results.*eholds the last exception.nilresults are printed asnil.
Line editing
When clojurust is built with the enable-rustyline feature, the REPL uses
rustyline for line editing, including
history and readline-style key bindings.
Without that feature, a simpler line reader is used that still supports multi-line input but has no history or key bindings.
Example session
$ cljrs repl
clojurust REPL (type :quit to exit)
=> (+ 1 2)
3
=> (def x 42)
=> x
42
=> (map inc [1 2 3])
(2 3 4)
=> :quit
Bye.
cljrs eval
Evaluate a single Clojure expression and print the result.
cljrs eval '<EXPR>'
The expression is evaluated in a fresh environment with the standard library
loaded. If the result is non-nil, it is printed to stdout. A nil result
produces no output.
Arguments
| Argument | Description |
|---|---|
<EXPR> | The expression to evaluate, as a string |
Examples
cljrs eval '(+ 1 2)'
# → 3
cljrs eval '(map str (range 5))'
# → ("0" "1" "2" "3" "4")
cljrs eval '(println "hello")'
# prints: hello
# (println returns nil so no value line is printed)
Notes
eval does not accept --src-path. If you need to require namespaces
from a source tree, use run with a small script file instead.
cljrs compile
AOT-compile a source file to a standalone native binary.
cljrs compile [OPTIONS] <FILE> --out <OUT>
The compiler lowers the source file through the IR pipeline and emits a native
binary via Cranelift. The resulting binary statically links the clojurust
runtime, GC, and standard library; it has no runtime dependency on the cljrs
tool.
Arguments
| Argument | Description |
|---|---|
<FILE> | Source file to compile (or a directory when --test is used) |
Required options
-o, --out <OUT>
Output path for the compiled binary.
Optional options
--src-path <DIR>
Add DIR to the source path for require resolution. May be repeated.
--test
Compile a test harness instead of a regular program. When this flag is set,
FILE should be a directory; the compiler discovers all .cljrs/.cljc files
in that directory and builds a binary that runs all clojure.test tests found
in them.
--gc-soft-limit-mb <MB> / --gc-hard-limit-mb <MB>
GC memory limits baked into the compiled binary, not the compilation process itself.
Examples
# Compile a single file
cljrs compile src/myapp/core.cljrs --out myapp
# Compile and run
cljrs compile src/myapp/core.cljrs --out myapp && ./myapp
# Compile a test binary
cljrs compile --test test/ --out run-tests && ./run-tests
Notes
AOT compilation is based on Cranelift. Not all language features are yet supported in AOT mode; in particular, features that rely on dynamic dispatch or late binding may fall back to interpreted execution within the compiled binary.
cljrs test
Run clojure.test test namespaces.
cljrs test [OPTIONS] [NAMESPACES...]
Loads each namespace, calls clojure.test/run-tests on it, and prints a
summary of passes, failures, and errors. Exits with code 0 if all tests
pass, 1 if any fail or error, and 2 if no test namespaces are found.
Arguments
| Argument | Description |
|---|---|
[NAMESPACES...] | Namespace names to test (e.g. myapp.core-test). If omitted, all namespaces in --src-path directories are discovered automatically. |
Options
--src-path <DIR>
Source directory to search for test namespaces. May be repeated. Namespace
discovery translates file paths to namespace names by replacing path separators
with . and underscores with -.
cljrs test --src-path test
-v, --verbose
Print each passing assertion as well as failures. Useful for identifying which test is hanging.
--gc-soft-limit-mb <MB> / --gc-hard-limit-mb <MB>
GC memory limits. See run for details.
Namespace discovery
When no explicit namespaces are given, cljrs test walks all --src-path
directories and converts every .cljrs and .cljc file to a namespace name:
test/myapp/core_test.cljrs → myapp.core-test
test/myapp/util_test.cljc → myapp.util-test
Output format
Ran 12 tests containing 48 assertions across 2 namespace(s) in 0.3s.
48 passed, 0 failed, 0 errors.
All tests passed.
══════════════════════════════════════════════════════════════
On failure, a breakdown by namespace is printed before the summary line.
Examples
# Run all tests discovered under test/
cljrs test --src-path test
# Run specific namespaces
cljrs test --src-path test myapp.core-test myapp.util-test
# Verbose output
cljrs test --src-path test --verbose
cljrs deps
Manage project dependencies declared in cljrs.edn.
cljrs deps <SUBCOMMAND>
Subcommands
| Subcommand | Description |
|---|---|
fetch | Clone or update git dependencies |
status | Show which dependencies are cached and which are missing |
fetch
cljrs deps fetch [NAME]
Clone or update git dependencies from cljrs.edn. Without a NAME, fetches
every git dependency declared in the nearest cljrs.edn. With a NAME, fetches
only that one dependency.
Git repositories are cached in ~/.cljrs/cache/git/. Network access only
occurs when this command is run explicitly — the runtime never fetches
dependencies automatically.
If a versioned symbol or namespace requires a git dependency that is not in the local cache, the runtime raises a clear error:
error: dependency 'my.lib' is not cached locally.
run `cljrs deps fetch` to download it.
Examples
cljrs deps fetch # fetch all git deps
cljrs deps fetch my.lib # fetch only 'my.lib'
status
cljrs deps status
Print the cache status of every dependency declared in the nearest cljrs.edn.
my.lib: cached (sha: abc1234ef, url: https://github.com/user/my-lib)
dev-tools: NOT cached — run `cljrs deps fetch` (sha: 9f3a112b, url: ...)
vendor: local dep at ../vendor/utils — ok
Exits with code 0 if all dependencies are satisfied, 1 otherwise.
cljrs.edn format
clojurust discovers project configuration by walking up the directory tree from
the current working directory until it finds a cljrs.edn file. The file is
valid clojurust EDN:
{:paths ["src" "resources"]
:deps
{my.lib {:git/url "https://github.com/user/my-lib"
:git/sha "abc1234ef"}
dev-tools {:git/url "https://github.com/user/dev-tools"
:git/sha "9f3a112b"}
vendor {:local/root "../vendor/utils"}}
:aliases
{:dev {:extra-paths ["dev"]}
:test {:extra-paths ["test"]
:extra-deps {test-tools {:git/url "..."
:git/sha "..."}}}}
:verify-commit-signatures true}
Keys
| Key | Type | Description |
|---|---|---|
:paths | vector of strings | Directories to add to the source path. Equivalent to --src-path on the CLI. |
:deps | map | Map from dependency name (symbol) to dependency descriptor. |
:aliases | map | Named alias maps with :extra-paths and :extra-deps. |
:verify-commit-signatures | boolean | If true, require GPG/SSH signatures on all versioned commits. |
Dependency descriptors
Git dependency:
my.lib {:git/url "https://github.com/user/my-lib"
:git/sha "abc1234ef"}
:git/sha must be at least a 7-character commit prefix. The full commit hash
is recommended for reproducibility.
Local dependency:
vendor {:local/root "../vendor/utils"}
:local/root is a path relative to the cljrs.edn file’s directory.
cljrs ir-viz
Render the optimised intermediate representation (IR) for a source file to a self-contained HTML page.
cljrs ir-viz [OPTIONS] <FILE>
The HTML output shows the source side-by-side with the IR, with regions colour-coded by the bump-allocation optimiser’s results. Allocations that did not make it into a region are annotated with their escape verdict and the blamed use site.
This subcommand is primarily a debugging aid for the IR optimisation pipeline.
Arguments
| Argument | Description |
|---|---|
<FILE> | Source file to lower to IR |
Options
-o, --out <FILE>
Output path for the HTML file. If omitted, the output is written alongside
the source file with an .ir.html extension:
src/myapp/core.cljrs → src/myapp/core.cljrs.ir.html
--src-path <DIR>
Add DIR to the source path for require resolution. May be repeated.
--quiet
Suppress the [ir-viz] wrote … progress line on stderr.
Example
cljrs ir-viz src/myapp/core.cljrs
# writes: src/myapp/core.cljrs.ir.html
cljrs ir-viz src/myapp/core.cljrs --out /tmp/core.html --quiet
Open the resulting HTML file in a browser to explore the IR.
Interpreting the output
- Green regions — allocations placed in a bump-allocation region; they do not incur GC heap pressure.
- Red / yellow annotations — allocations that escaped the region, labelled with the reason (returned, captured by closure, stored in heap object, etc.).
- Clicking a source line highlights the corresponding IR instructions and vice versa.
Language overview
clojurust is a dialect of Clojure. Its syntax, data model, and core library are designed to be as compatible with Clojure as possible, with a small number of deliberate extensions and a small number of features that are not yet implemented.
What is the same
- All Clojure literal syntax: symbols, keywords, numbers (long, double, ratio, BigInt, BigDecimal), strings, characters, booleans, nil.
- All collection literals: list
(...), vector[...], map{...}, set#{...}. - Reader dispatch macros:
',`,~,~@,^,@,#',#(...),#"...",##Inf,##-Inf,##NaN, tagged literals. - The full set of special forms:
def,fn*,if,do,let*,loop*,recur,quote,var,set!,throw,try/catch/finally,letfn,binding. - Persistent collections (HAMT-backed maps and sets, RRB vectors, linked lists, queues) with Clojure-compatible equality and hashing.
clojure.core— arithmetic, comparison, collection operations, lazy sequences, transducers, I/O, concurrency primitives.- Standard library namespaces:
clojure.string,clojure.set,clojure.test,clojure.walk,clojure.edn,clojure.zip,clojure.data. - Protocols (
defprotocol,extend-type,extend-protocol), multimethods (defmulti,defmethod), records (defrecord), andreify. - Concurrency:
atom,future,promise,delay,volatile!,agent. - Dynamic variables (
binding,with-bindings,*ns*,*out*, etc.). - Metadata on vars and some values (
with-meta,meta,^:dynamic, etc.).
Extensions
- Reader conditionals — the
:rustplatform key. - Versioned symbols —
my-fn@abc1234syntax. - A small set of new built-in functions with no Clojure equivalent.
Known differences and missing features
See Differences from Clojure for the full list.
Reader conditionals
Reader conditionals allow a single source file to contain code for multiple
Clojure platforms. clojurust evaluates the :rust branch.
Syntax
Non-splicing form
#?(:rust expr-rust
:clj expr-jvm
:cljs expr-clojurescript
:default expr-fallback)
Exactly one branch is selected at read time based on the current platform. For
clojurust, :rust is matched first. If no :rust key is present, :default
is used. If neither is present, the entire form is skipped (reads as nothing).
The selected branch is a single expression; the whole #?(...) form evaluates
to that expression.
(def platform #?(:rust "clojurust"
:clj "JVM Clojure"
:cljs "ClojureScript"
:default "unknown"))
Splicing form
#?@(:rust [a b c]
:clj [x y z]
:default [])
The splicing form #?@(...) selects a vector from the active platform and
splices its elements into the surrounding form. It is only valid inside a list,
vector, map, or set literal.
;; Adds platform-specific items to a vector
(def features [#?@(:rust [:gc :cranelift]
:clj [:jvm :hotspot]
:default [])])
; => [:gc :cranelift] (on clojurust)
;; Platform-specific require in an ns form
(ns myapp.core
(:require [clojure.string :as str]
#?@(:rust [[:clojurust.system :as sys]]
:clj [[:java.lang.System :as sys]])))
File-extension behaviour
| Extension | Platform dispatch |
|---|---|
.cljrs | Always :rust. Reader conditionals are still supported but :rust is always the active branch. |
.cljc | Cross-platform. Reader conditional branches are stored as-is; the evaluator selects :rust. |
Notes
- The reader stores all branches of a
#?(...)form; only the evaluator discards non-matching branches. This means reader-conditional forms can be inspected programmatically without losing the other branches. - Order within a reader conditional matters: keys are checked left-to-right.
:defaultshould come last. - Unlike Clojure, there is no
:cljr(ClojureCLR) platform; the clojurust key is:rust.
Versioned symbols
clojurust lets you pin a symbol or namespace to a specific git commit by
appending @<commit> to its name. This lets callers use a historical
implementation without requiring the defining library to keep the old code
alongside the new.
Syntax
my-fn@abc1234 ; unqualified versioned symbol
my.ns/my-fn@abc1234 ; namespace-qualified versioned symbol
The commit suffix must be a valid hex prefix of at least 7 characters (the full 40-character hash is recommended for reproducibility).
Versioned require
Whole namespaces can be loaded at a specific commit:
(require '[my.lib@abc1234 :as lib-v1])
(require '[my.lib :as lib]) ; HEAD
(lib/some-fn x) ; current version
(lib-v1/some-fn x) ; pinned to abc1234
Both aliases coexist in the same namespace; calls through lib-v1/ always
resolve against commit abc1234.
Propagation semantics
When a function body is evaluated in a versioned context — because it was
loaded via a versioned require or called through a versioned symbol — the
following resolution rules apply:
| Symbol form | Resolved at |
|---|---|
Unqualified or same-namespace, no @ | The inherited commit (propagated from the caller) |
Explicitly versioned foo@D | Commit D |
External / cross-namespace, no @ | HEAD (current) |
This means a versioned call behaves like a logical snapshot: internal helpers in the same namespace are drawn from the same commit automatically, but cross-namespace dependencies and the standard library use their current values unless explicitly pinned.
Dependency setup
Versioned symbols require the referenced git repository to be cached locally.
Declare the dependency in cljrs.edn and run cljrs deps fetch before using
versioned symbols:
; cljrs.edn
{:deps
{my.lib {:git/url "https://github.com/user/my-lib"
:git/sha "abc1234ef"}}}
cljrs deps fetch my.lib
If the required commit is not cached, clojurust raises a descriptive error rather than attempting a network fetch:
error: dependency 'my.lib' is not cached locally.
run `cljrs deps fetch` to download it.
Signature verification
When --verify-commit-signatures is passed on the CLI (or
:verify-commit-signatures true is set in cljrs.edn), clojurust verifies
that every accessed versioned commit carries a valid GPG or SSH signature
before executing its code.
Notes
- Versioned symbols are resolved lazily at call time, not at load time, so the dependency only needs to be cached the first time the code path is actually executed.
- The version cache is per-
GlobalEnvand is keyed on"<ns>/<name>@<commit>", so the same commit of the same namespace is loaded at most once per interpreter session.
Differences from Clojure
This page documents intentional differences, missing features, and behavioural
variations between clojurust and Clojure (JVM). The goal is to be a useful
reference for porting .cljc code and for understanding what to expect when
running Clojure code under clojurust.
No JVM, no Java interop
clojurust runs on Rust, not the JVM. There is no Java class hierarchy, no
java.lang.*, and no Java method calls. The . (dot) special form and new
have limited implementations:
(new Exception "msg")and(Exception. "msg")produce clojurust exception values, not Java objects.(.method obj args...)is not yet implemented. Use protocols or the built-in equivalents instead.
Code that uses (System/nanoTime), (Thread/sleep n), or any other Java
static method must use reader conditionals to supply
a :rust alternative, or use the clojurust built-ins nanotime and sleep
respectively.
Platform key
The reader-conditional platform key is :rust, not :clj. See
Reader conditionals.
Missing concurrency features
| Feature | Status |
|---|---|
ref / STM (dosync, alter, ref-set, commute, ensure) | Not implemented |
locking macro | Not implemented |
monitor-enter / monitor-exit | Not implemented |
atom, agent, future, promise, delay, and volatile! are fully
implemented.
deftype
deftype is not implemented. Use defrecord (which is fully supported) or
reify for most cases.
Metadata on collections
Metadata is supported on vars and some values, but not yet propagated through
collection operations such as assoc. The with-meta and meta functions
work on any value that carries metadata.
Sorted collections
sorted-map and sorted-set are implemented. sorted-map-by and
sorted-set-by (custom comparators) are not yet implemented.
Hierarchies
make-hierarchy, ancestors, descendants, and parents have stub
implementations. derive, underive, and a full isa? hierarchy are not yet
implemented. defmulti / defmethod dispatch works but does not consult a
custom hierarchy.
amap and areduce
These macros are registered as stubs but not fully implemented.
clojure.pprint
Not implemented.
clojure.zip
Stub — the namespace exists but most functions are not yet implemented.
Numeric tower
The numeric tower (Long → BigInt → Ratio → BigDecimal → Double) follows Clojure conventions. A few differences to be aware of:
- Integer overflow in
+,-,*automatically promotes toBigInt(same as Clojure’scheckedarithmetic). The promoting variants+',-',*'are also available. (/ 1 3)returns aRatio(1/3), not aDouble, same as Clojure.- BigDecimal precision is controlled by
with-precision(the Clojure macro) or the lower-levelpush-precision!/pop-precision!built-ins.
*clojure-version* / *cljrs-version*
These vars are not yet defined. clojure-version as a function returns a
map describing the current runtime.
with-open and close
clojurust provides RAII-style resource management via with-open (a macro)
and close (a built-in function). These follow the same protocol as Clojure’s
with-open; any value that implements the Resource protocol can be used.
Source file namespace mapping
The namespace→file mapping converts . to / and - to _, the same as
Clojure:
myapp.core → myapp/core.cljrs (or .cljc)
my-app.utils → my_app/utils.cljrs
Standard library
The following clojure.* namespaces are available:
clojure.string, clojure.set, clojure.test, clojure.walk,
clojure.edn, clojure.data.
clojure.zip and clojure.pprint exist as stubs. clojure.spec.alpha,
clojure.core.async, and clojure.core.match are not available.
New built-in functions
clojurust adds a small number of built-in functions that have no direct equivalent in standard Clojure. Most exist because Clojure code would normally reach these capabilities through Java interop, which is not available in clojurust.
System / time
(sleep ms)
Pause the current thread for ms milliseconds.
(sleep 100) ; sleep 100 ms
Clojure equivalent: (Thread/sleep ms).
(nanotime)
Return the number of nanoseconds since the Unix epoch as a Long.
(let [start (nanotime)
_ (do-work)
end (nanotime)]
(println "elapsed ns:" (- end start)))
Clojure equivalent: (System/nanoTime) (note: Clojure’s version is relative to
an arbitrary origin; clojurust’s is Unix epoch-relative).
String utilities
(char-code c)
Return the Unicode code point of character c as a Long.
(char-code \A) ; => 65
(char-code \λ) ; => 955
Clojure equivalent: (int c).
(char-at s i)
Return the character at index i in string s.
(char-at "hello" 1) ; => \e
Clojure equivalent: (.charAt s i).
(string->list s)
Convert string s to a list of its characters.
(string->list "abc") ; => (\a \b \c)
Clojure equivalent: (seq s) (returns a seq, not a list, but behaves the same
in most contexts).
(number->string n)
Convert number n to its string representation.
(number->string 42) ; => "42"
(number->string 3.14) ; => "3.14"
Clojure equivalent: (str n).
(string->number s) / (string->number s base)
Parse string s as a number, returning nil if the string is not a valid
number. The optional base argument specifies the radix (default 10).
(string->number "42") ; => 42
(string->number "3.14") ; => 3.14
(string->number "ff" 16) ; => 255
(string->number "nope") ; => nil
Clojure equivalent: no single equivalent; typically (Integer/parseInt s),
(Double/parseDouble s), or a try/catch around those.
BigDecimal precision
(push-precision! n) / (push-precision! n mode)
Push a BigDecimal precision context onto the thread-local precision stack.
Subsequent BigDecimal operations are rounded to n significant digits using
mode (default HALF_UP).
Available rounding modes: CEILING, FLOOR, HALF_UP, HALF_DOWN,
HALF_EVEN, UP, DOWN, UNNECESSARY.
(push-precision! 4)
(/ 1M 3M) ; => 0.3333 (4 significant digits)
(pop-precision!)
This is the lower-level mechanism underlying the with-precision macro (which
is preferred in normal code). Use push-precision! / pop-precision! only
when you need to manage the precision stack manually across multiple calls.
Clojure equivalent: with-precision (macro).
(pop-precision!)
Pop the most recently pushed BigDecimal precision context.
Persistent queue
(queue) / (queue capacity)
Create a new empty persistent queue. The optional capacity argument is a size
hint for the initial allocation.
(def q (queue))
(def q2 (conj q :a :b :c))
(peek q2) ; => :a
(pop q2) ; => queue with [:b :c]
Clojure equivalent: clojure.lang.PersistentQueue/EMPTY (a Java static field).
Mutable ArrayList
These functions provide a mutable, GC-managed resizable array backed by a Rust
Vec. They are intended for performance-sensitive code that builds up a
collection before converting it to an immutable value, or for interoperating
with Rust code that expects a mutable sequence.
An ArrayList value is a NativeObject; it is not a Clojure collection and
cannot be used with seq, conj, map, etc. directly. Convert it with
array-list-to-array first.
(array-list) / (array-list capacity)
Create a new empty ArrayList. With a Long argument, pre-allocates storage
for capacity elements.
(def al (array-list 16))
(array-list-push al v)
Append value v to the end of al. Returns al (mutates in place).
(array-list-push al :x)
(array-list-push al :y)
(array-list-remove al i)
Remove and return the element at index i. Later elements shift left.
(array-list-remove al 0) ; removes and returns first element
(array-list-length al)
Return the number of elements in al as a Long.
(array-list-length al) ; => 2
(array-list-to-array al)
Convert al to an immutable object array (Value::ObjectArray). The
ArrayList is unaffected.
(def arr (array-list-to-array al))
(alength arr) ; => 2
(array-list-clear al)
Remove all elements from al. Returns al.
(array-list-clear al)
Rust interop
(native-object? x)
Return true if x is a NativeObject (a Rust value wrapped for use in
clojurust), false otherwise.
(native-object? (array-list)) ; => true
(native-object? [1 2 3]) ; => false
(native-type x)
Return the type-tag string of NativeObject x, or nil if x is not a
NativeObject.
(native-type (array-list)) ; => "ArrayList"
(native-type 42) ; => nil
The type tag is set by the Rust code that implements the NativeObject trait
and is the primary mechanism for dispatching on native types from clojurust
code.