Liking cljdoc? Tell your friends :D

boring.records

Build a record registry without naming every record by hand.

Two mechanisms, because the platforms differ in what is knowable when:

  • auto-registry (macro, both platforms) resolves at COMPILE time. It asks the compiler which records exist and emits a literal map of wire name to constructor. Nothing is resolved from wire content at run time, so the set of constructible types is fixed when you build. This is the only mechanism that can work on ClojureScript, and it is the safer one on the JVM too.

  • {:auto-construct-records? true} (JVM only, a decode option) resolves at run time from the class name on the wire. Use it when the record types are not known at build time -- a plugin, a REPL, a dynamically loaded namespace. See doc/SECURITY.md for exactly what it relaxes.

The compile-time route is preferred wherever it fits.

Build a record registry without naming every record by hand.

Two mechanisms, because the platforms differ in what is knowable when:

- **`auto-registry` (macro, both platforms)** resolves at COMPILE time. It
  asks the compiler which records exist and emits a literal map of wire name
  to constructor. Nothing is resolved from wire content at run time, so the
  set of constructible types is fixed when you build. This is the only
  mechanism that can work on ClojureScript, and it is the safer one on the
  JVM too.

- **`{:auto-construct-records? true}` (JVM only, a decode option)** resolves
  at run time from the class name on the wire. Use it when the record types
  are not known at build time -- a plugin, a REPL, a dynamically loaded
  namespace. See doc/SECURITY.md for exactly what it relaxes.

The compile-time route is preferred wherever it fits.
raw docstring

auto-registryclj/smacro

(auto-registry)
(auto-registry prefix)

A registry that can reconstruct every defrecord the compiler knows about.

Resolved at COMPILE time and emitted as a literal map, so it works under ClojureScript advanced compilation -- where constructor names are minified and there is no runtime resolve -- and performs no lookup driven by wire content on either platform.

(def registry (boring/auto-registry))
(boring/decode bs {:registry registry})

prefix is a literal string, for narrowing to your own namespaces:

(boring/auto-registry "my.app")

A literal rather than a predicate function on purpose: the macro would have to eval a function to apply it at expansion time, and during ClojureScript macroexpansion *ns* is not a namespace where that is reliable: a predicate function failed to resolve = at expansion time.

Records defined AFTER this expands are not included; that is the trade for resolving nothing at run time. On the JVM, {:auto-construct-records? true} covers the dynamic case.

This sees more than your require graph. On the JVM it sees namespaces LOADED when it expands, and loading is global -- a namespace pulled in by something unrelated is visible to a caller that never required it, so the same source can yield different registries in a REPL and in an AOT build. On ClojureScript it reads the compiler's analysis cache, which holds every namespace in the BUILD, so the no-prefix form picks up records from namespaces the caller never mentions.

The prefix is what makes the result predictable. registry-for names its inputs exactly; prefer it when the contents matter.

A registry that can reconstruct every defrecord the compiler knows about.

Resolved at COMPILE time and emitted as a literal map, so it works under
ClojureScript advanced compilation -- where constructor names are minified
and there is no runtime `resolve` -- and performs no lookup driven by wire
content on either platform.

    (def registry (boring/auto-registry))
    (boring/decode bs {:registry registry})

`prefix` is a literal string, for narrowing to your own namespaces:

    (boring/auto-registry "my.app")

A literal rather than a predicate function on purpose: the macro would
have to `eval` a function to apply it at expansion time, and during
ClojureScript macroexpansion `*ns*` is not a namespace where that is
reliable: a predicate function failed to resolve `=` at expansion time.

Records defined AFTER this expands are not included; that is the trade for
resolving nothing at run time. On the JVM, `{:auto-construct-records?
true}` covers the dynamic case.

**This sees more than your require graph.** On the JVM it sees namespaces
LOADED when it expands, and loading is global -- a namespace pulled in by
something unrelated is visible to a caller that never required it, so the
same source can yield different registries in a REPL and in an AOT build.
On ClojureScript it reads the compiler's analysis cache, which holds every
namespace in the BUILD, so the no-prefix form picks up records from
namespaces the caller never mentions.

The prefix is what makes the result predictable. `registry-for` names its
inputs exactly; prefer it when the contents matter.
sourceraw docstring

registry-forclj/smacro

(registry-for & ns-syms)

A registry for the records in exactly these namespaces. Deterministic.

(records/registry-for my.app.model my.app.events)

Prefer this over auto-registry when it matters what the registry contains. On the JVM auto-registry scans namespaces that are LOADED when it expands, and loading is global: a namespace pulled in by something unrelated is visible to a caller that never required it, so the same source can produce different registries in a REPL and in an AOT build. This arity names its inputs, and on the JVM requires them first, so the answer does not depend on what else happened to be loaded.

On ClojureScript the named namespaces must be required by the calling namespace as usual -- the macro reads the compiler's analysis cache and cannot cause a namespace to be analysed.

A registry for the records in exactly these namespaces. Deterministic.

    (records/registry-for my.app.model my.app.events)

Prefer this over `auto-registry` when it matters what the registry
contains. On the JVM `auto-registry` scans namespaces that are LOADED when
it expands, and loading is global: a namespace pulled in by something
unrelated is visible to a caller that never required it, so the same
source can produce different registries in a REPL and in an AOT build.
This arity names its inputs, and on the JVM requires them first, so the
answer does not depend on what else happened to be loaded.

On ClojureScript the named namespaces must be required by the calling
namespace as usual -- the macro reads the compiler's analysis cache and
cannot cause a namespace to be analysed.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close