tur/unique
uniqueness-type patterns (with-unique, consume, replace).
Reusable forms for the recurring "linear-resource" shapes that user code otherwise open-codes around ^unique / ref<T>: a scoped unique binding, threading a unique value through one transforming call, and swapping a unique value out for a replacement. The forms add no new capability kind -- they wrap the existing ^unique discipline (UT0-UT1) so the manual annotations stay in one place.
Auto-loaded only under -Xunique-types; default (by-value) builds and their codegen snapshots are unaffected. Wrapped in (defmodule tur/unique ...): the auto-load boundary is re-anchored after (load ...) expansion, so the last auto-loaded stdlib module's exported macros (with-unique) are promoted to global visibility alongside its defns -- no explicit import needed from user code. See docs/archive/history/autoload-defmodule-macro-not-promoted.md.
Since: UT3
with-unique
(with-unique [binding & body])
scope a uniquely-owned binding over a body.
Expands to a let whose binding is annotated ^unique, so the bound value is checked for the at-most-one-reference discipline across the body without the caller hand-writing the annotation.
| binding | a two-element form [name init]: the binding name and its | |
| uniquely-owned initializer | ||
| body | one or more expressions evaluated with name in scope |
The value of the last body expression.
(with-unique [u (make-ref 42)] ; u : ^unique (use-once u)) ; consumed exactly once
Since: UT3
consume
(consume [A B])
thread a unique value through a single transforming call.
Hands the uniquely-owned x to f, transferring ownership into the call. The point is to make the consume-and-pass step explicit at the call site; it lowers to a plain application (f x).
| x | the uniquely-owned value to consume | |
| f | a function that takes ownership of x and returns a result |
The result of (f x).
(consume buf buf-finish) ; => the result of (buf-finish buf)
Since: UT3
replace
(replace [A])
displace a unique value, returning the old one.
The value-semantics stand-in for mem::replace: consumes the uniquely-owned old and yields it back to the caller as the displaced value, while taking ownership of new as the replacement. A full replace-through-a-cell (writing new back into a mutable ref<T> slot) awaits a ref-set primitive; this form captures the consume-old / accept-new shape at the call site without new codegen.
| old | the uniquely-owned value being displaced | |
| new | the replacement value, consumed into the swap |
The displaced old value, for the caller to inspect or drop.
(let [displaced (replace current next)] (drop! displaced)) ; old `current` handed back for disposal
Since: UT3