This is the chain Reference Manual, version 0.4.0, generated automatically by Declt version 4.0 beta 2 "William Riker" on Fri May 15 11:40:19 2026 GMT+0.
The main system appears first, followed by any subsystem dependency.
chainChaining/threading macros, one of them ‘setf‘ing its first argument
Thomas Bartscher <thomas-bartscher@weltraumschlangen.de>
BSD-3
0.4.0
metabang-bind (system).
mgl-pax (system).
package.lisp (file).
chain.lisp (file).
Files are sorted by type and then listed depth-first from the systems components trees.
chain/package.lispchain (system).
@chain (special variable).
@reference (special variable).
write-readme (function).
chain/chain.lisppackage.lisp (file).
chain (system).
chop (macro).
expand-chain (function).
value-form (function).
Packages are listed by definition order.
chaincommon-lisp.
metabang.bind.
mgl-pax.
@chain (special variable).
@reference (special variable).
chop (macro).
expand-chain (function).
value-form (function).
write-readme (function).
Definitions are sorted by export status, category, package, and then by lexicographic order.
Thread a value through a series of transformations, where ‘<>‘ represents the
value of the last transformation.
- Arguments
+ ‘argument‘
Initial value. Supports ‘:let‘ as in the body.
+ ‘body‘
Forms to apply sequentially. Each form has ‘<>‘ bound as an
anaphoric variable bound to the return value of the previous form in the
body.
Each form may be:
* A symbol
This is taken to be the name of a function, and called on the result
of the previous form
Note that ‘<>‘ as a bare symbol form also will be interpreted in
this way, and *not* as a variable.
* A regular form
Evaluated normally. Gets its semantics from ‘<>‘ being bound to the
result of the previous form.
* ‘(:let [var] [form])‘
Binds ‘[var]‘ to the result of ‘[form]‘ in the remainder of the
chain.
* ‘(:call [funcallable])‘
‘[funcallable]‘ needs to evaluate to a funcallable object. Calls
that object onto the previous value.
Can be understood as
“‘lisp
(funcall [funcallable] <>)
“‘
* ‘(:req [form])‘
If ‘[form]‘ returns nil, the whole macro call will short-circuit and
return nil without evaluating further forms. If ‘[form]‘ returns a
non-nil value, that value is taken to be the value of the ‘:req‘
form.
Can be understood as
“‘lisp
(or [form] (bail))
“‘
* ‘(:req [predicate] [form])‘
Evaluates ‘[form]‘ as usual, then checks whether ‘[predicate]‘
returns nil on the result. If it does, short circuit and return
‘nil‘ from ‘=>‘, otherwise continue with the computed value.
Can be understood as
“‘lisp
(let ((value [form]))
(if ([predicate] value)
value
(bail)))
“‘
* ‘(:cond [form])‘
If the ‘[form]‘ returns nil, the value of the ‘:cond‘ form is taken
to be the value of the previous form. Otherwise the value of the
‘:cond‘ form is the value of ‘[form]‘.
Can be understood as
“‘lisp
(or [form] <>)
“‘
* ‘(:cond [predicate] [form])‘
Evaluates ‘[form]‘ as usual, then checks whether ‘[predicate]‘
returns nil on the result. If it does, return the value of the
previous form, otherwise continue with the computed value.
Can be understood as
“‘lisp
(let ((value [form]))
(if ([predicate] value)
value
<>))
“‘
* ‘(lambda ([argument]) [body])‘
This is called on the result of the previous form.
‘:let‘, ‘:req‘, and ‘:cond‘ can be nested directly in each
other. ‘:call‘ can be nested inside the other forms.
Inside ‘body‘ the ‘bail‘ and ‘finish‘ macros are defined. They allow to
return from the ‘=>‘ form early. ‘bail‘ takes an optional and ‘finish‘ a
required argument for a return value. ‘finish‘ is supplied for easier
switching between ‘=>‘ and ‘set=>‘.
Note that, unlike other chaining/threading macros, ‘=>‘ does *not*
support something like this:
“‘lisp
!(=> ’(1 2 3)
! (remove-if #’evenp)
! (mapcar #’-))
“‘
This would not compile, with ‘remove-if‘ and ‘mapcar‘ not being supplied
enough arguments.
- Return value
Returns the value of its last form, or, should ‘bail‘ or ‘finish‘ be called,
the value of their argument, defaulting to ‘nil‘ for ‘bail‘.
- Examples
“‘cl-transcript
;;; basic usage
(=> 5
(* <> 2) ; => 10
1+)
=> 11
(defun sigmoid (x)
(=> x
- exp 1+ /))
(sigmoid 0)
=> 0.5
;;; lambda form usage
(=> 5
(lambda (x) ; => 8
(+ x 3))
(* <> 2))
=> 16
;;; using ‘:let‘
(defun triangle (n)
(=> (:let a n)
1+
(* <> a)
(/ <> 2)))
(triangle 10)
=> 55
;;; using ‘:call‘
(defun f^2 (f x)
(=> x
(:call f)
(:call f)))
(f^2 (lambda (x)
(* x x))
10)
=> 10000
;;; using ‘:req‘
(defun negate-first-even (xs)
(=> xs
(:req (first (member-if #’evenp
<>)))
-))
(negate-first-even ’(1 2 3))
=> -2
(negate-first-even ’(1 3))
=> NIL
(defun maybe-halve (x)
(=> x
(:req integerp (/ <> 2))))
(maybe-halve 3)
=> NIL
(maybe-halve 4)
=> 2
;;; using ‘:cond‘
(defun negate-first-prefer-even (xs)
(=> xs
(:cond (member-if #’evenp
<>))
first -))
(negate-first-prefer-even ’(1 2 3))
=> -2
(negate-first-prefer-even ’(1 3))
=> -1
(defun halve-even (x)
(=> x
(:cond integerp (/ <> 2))))
(halve-even 3)
=> 3
(halve-even 4)
=> 2
;;; using ‘bail‘
(defun halve-and-inc-maybe (x)
(=> x
(if (evenp <>)
(/ <> 2)
(bail))
1+))
(halve-and-inc-maybe 3)
=> NIL
(halve-and-inc-maybe 4)
=> 3
;;; ‘finish‘ examples can be derived by replacing ‘(bail)‘ with
;;; ‘(finish nil)‘ in the ‘bail‘ examples.
“‘
Version of ‘def=>‘ with explicitly supplied arguments. More general since it can accept more than one argument. The first argument is the argument to the ‘=>‘ call.
Defines a function named ‘name‘ taking one argument. The argument is threaded through the ‘body‘ like in ‘=>‘. Supports all the special forms that ‘=>‘ does.
- Examples
“‘cl-transcript
(def=> logistic-curve
- exp 1+ /)
(logistic-curve 0)
=> 0.5
“‘
Version of ‘lambda=>‘ with explicitly supplied arguments. More general since it can accept more than one argument. The first argument is the argument to the ‘=>‘ call.
Returns a lambda taking one argument. The argument is threaded through the
‘body‘ like in ‘=>‘. Supports all the special forms that ‘=>‘ does.
- Examples
“‘cl-transcript
(funcall (lambda=> - exp 1+ /)
0)
=> 0.5
“‘
Thread the initial value of a place through transformations like in macro
‘=>‘, and update the place with the final result.
- Arguments
+ ‘argument‘
A ‘setf‘-able place.
+ ‘body‘
Exactly the same as in ‘=>‘. Supports ‘:let‘, ‘:call‘, ‘:req‘, ‘:cond‘,
‘lambda‘, ‘<>‘, ‘bail‘, and ‘finish‘.
‘:req‘ and ‘(bail)‘ will short-circuit such that the place will not be
set. ‘(finish [value])‘ will short-circuit and set the place to
‘[value]‘.
- Return value
Returns the value of its last form.
- Side effects
Updates PLACE to the calculated result.
- Examples
“‘cl-transcript
(defstruct box
value)
;;; basic usage
(let ((x 5))
(set=> x
(* <> 2) ; => 10
1+) ; => 11
x)
=> 11
;;; using ‘:let‘
(defun triangle! (box)
(set=> (:let a (box-value box))
1+
(* <> a)
(/ <> 2)))
(let ((box (make-box :value 10)))
(triangle! box)
(box-value box))
=> 55
;;; using ‘:req‘
(defun maybe-only-even! (box)
(set=> (box-value box)
(:req (remove-if-not #’evenp
<>))))
(let ((box (make-box :value ’(1 2 3 4 5 6))))
(maybe-only-even! box)
(box-value box))
=> (2 4 6)
(let ((box (make-box :value ’(1 3 5))))
(maybe-only-even! box)
(box-value box))
=> (1 3 5)
(defun maybe-halve! (box)
(set=> (box-value box)
(:req integerp (/ <> 2))))
(let ((box (make-box :value 3)))
(maybe-halve! box)
(box-value box))
=> 3
(let ((box (make-box :value 4)))
(maybe-halve! box)
(box-value box))
=> 2
;;; using ‘bail‘
(defun double-odd-inc!-or-zero (box)
(set=> (box-value box)
(if (oddp <>)
(* <> 2)
(bail 0))
1+))
(let ((box (make-box :value 2)))
(values (double-odd-inc!-or-zero box)
(box-value box)))
=> 0
=> 2
(let ((box (make-box :value 3)))
(values (double-odd-inc!-or-zero box)
(box-value box)))
=> 7
=> 7
;;; using ‘finish‘
(defun double-odd-inc-or-zero! (box)
(set=> (box-value box)
(if (oddp <>)
(* <> 2)
(finish 0))
1+))
(let ((box (make-box :value 2)))
(values (double-odd-inc-or-zero! box)
(box-value box)))
=> 0
=> 0
(let ((box (make-box :value 3)))
(values (double-odd-inc-or-zero! box)
(box-value box)))
=> 7
=> 7
“‘
| Jump to: | =
C D E F L M S V W |
|---|
| Jump to: | =
C D E F L M S V W |
|---|
| Jump to: | @
S |
|---|
| Jump to: | @
S |
|---|
| Jump to: | C F P S |
|---|
| Jump to: | C F P S |
|---|