Global tables, in the spirit of Frink's single global namespace:
defunit registers every unit here (builtins
auto-register when commensura.units loads); the #commensura/quantity
reader resolves unit names here, so user-defined units reify too.register-unit-resolver! installs a pred/dispatch pair
that builds a whole family of names on demand (e.g. dollar_1960); resolve-unit
tries the table first, then resolvers, so families reify from the reader without
being registered one-by-one.commensura.dimensions/names (the ||| labels) and extended at runtime
via register-dimension!, so users can name their own dimensions.The two tables share a symmetric API — register-{unit,dimension}! (last-writer-
wins, warning when a name is redefined to a different value), lookup-{unit, dimension}, all-{units,dimensions}, clear-{units,dimensions}!.
The backing atoms (units, dim-names, unit-resolvers) are public — reach for
them directly when you want bulk / swap! / add-watch / reordering access. The
functions above are the ergonomic path that also applies the invariants (redefine
warnings, dimension-key normalization, reseed-on-clear); the atoms trust you to know
what you're doing.
Trade-off (documented): this is global mutable state. Unit vars remain lexically
namespaced and unaffected — only the string-keyed lookup / literal reification path is
global, and redefining a name via register-*! warns (last writer wins). For cold
deserialization, the defining defunit (or a resolver) must be loaded before a literal
that names its unit is read.
Global tables, in the spirit of Frink's single global namespace:
* a name -> unit table — `defunit` registers every unit here (builtins
auto-register when `commensura.units` loads); the `#commensura/quantity`
reader resolves unit names here, so *user*-defined units reify too.
* unit *resolvers* — `register-unit-resolver!` installs a `pred`/`dispatch` pair
that builds a whole *family* of names on demand (e.g. `dollar_1960`); `resolve-unit`
tries the table first, then resolvers, so families reify from the reader without
being registered one-by-one.
* a dimension-map -> human-name table — seeded from the generated
`commensura.dimensions/names` (the `|||` labels) and extended at runtime
via `register-dimension!`, so users can name their own dimensions.
The two tables share a symmetric API — `register-{unit,dimension}!` (last-writer-
wins, warning when a name is redefined to a *different* value), `lookup-{unit,
dimension}`, `all-{units,dimensions}`, `clear-{units,dimensions}!`.
The backing atoms (`units`, `dim-names`, `unit-resolvers`) are **public** — reach for
them directly when you want bulk / `swap!` / `add-watch` / reordering access. The
functions above are the ergonomic path that also applies the invariants (redefine
warnings, dimension-key normalization, reseed-on-clear); the atoms trust you to know
what you're doing.
Trade-off (documented): this is global mutable state. Unit *vars* remain lexically
namespaced and unaffected — only the string-keyed lookup / literal reification path is
global, and redefining a name via `register-*!` warns (last writer wins). For cold
deserialization, the defining `defunit` (or a resolver) must be loaded before a literal
that names its unit is read.(all-dimensions)The whole dims-map -> name table (for introspection).
The whole dims-map -> name table (for introspection).
(all-unit-resolvers)The installed resolvers, in registration order (for introspection).
The installed resolvers, in registration order (for introspection).
(all-units)The whole name -> unit map (for introspection).
The whole name -> unit map (for introspection).
(clear-dimensions!)Reset the dimension-name table to the builtin ||| seed, dropping user
registrations (for test isolation).
Reset the dimension-name table to the builtin `|||` seed, dropping user registrations (for test isolation).
(clear-unit-resolvers!)Remove all installed unit resolvers (for test isolation).
Remove all installed unit resolvers (for test isolation).
(clear-units!)Empty the unit registry (for test isolation).
Empty the unit registry (for test isolation).
(lookup-dimension d)Human name registered for dimension map d (builtin or user), or nil.
Human name registered for dimension map `d` (builtin or user), or nil.
(lookup-unit nm)The unit registered under string nm, or nil. A handy string-keyed unit API:
(lookup-unit "gallon").
The unit registered under string `nm`, or nil. A handy string-keyed unit API: `(lookup-unit "gallon")`.
(register-dimension! dims nm)Register (or override) the human name for a dimension map — e.g.
(register-dimension! {:length 4} "quaternary space"). Zero exponents are dropped
so the key matches a quantity's canonical dimensions (last writer wins; warns on a
differing redefine). Returns nm.
Register (or override) the human name for a dimension map — e.g.
`(register-dimension! {:length 4} "quaternary space")`. Zero exponents are dropped
so the key matches a quantity's canonical dimensions (last writer wins; warns on a
differing redefine). Returns `nm`.(register-unit! nm qty)Register unit qty under string nm (last writer wins; warns on a differing
redefine). Returns qty. What defunit calls.
Register unit `qty` under string `nm` (last writer wins; warns on a differing redefine). Returns `qty`. What `defunit` calls.
(register-unit-resolver! pred dispatch)Install a resolver for a family of units whose members are derivable from their name rather
than registered one-by-one (e.g. the historical dollar_1960). pred is name -> boolean;
dispatch is name -> unit, invoked when a name isn't in the unit table and pred matches.
Resolvers are tried in registration order; the first whose pred matches wins, and its dispatch
result — or exception — is the answer (so a matched-but-unbuildable name surfaces its own error,
not a generic "unknown unit"). Complements register-unit!/defunit (a single fixed unit).
Install a resolver for a *family* of units whose members are derivable from their name rather than registered one-by-one (e.g. the historical `dollar_1960`). `pred` is `name -> boolean`; `dispatch` is `name -> unit`, invoked when a name isn't in the unit table and `pred` matches. Resolvers are tried in registration order; the first whose `pred` matches wins, and its `dispatch` result — or exception — is the answer (so a matched-but-unbuildable name surfaces its own error, not a generic "unknown unit"). Complements `register-unit!`/`defunit` (a single fixed unit).
(resolve-unit nm)Resolve a unit by name: the registered unit, else the first matching resolver's dispatch, else
nil. The #commensura/… reader resolves through this, so builtins, user defunits, and resolver
families all reify.
Resolve a unit by name: the registered unit, else the first matching resolver's `dispatch`, else nil. The `#commensura/…` reader resolves through this, so builtins, user `defunit`s, and resolver families all reify.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |