The chain Reference Manual

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.

Table of Contents


1 Introduction


2 Systems

The main system appears first, followed by any subsystem dependency.


2.1 chain

Chaining/threading macros, one of them ‘setf‘ing its first argument

Author

Thomas Bartscher <>

License

BSD-3

Version

0.4.0

Dependencies
  • metabang-bind (system).
  • mgl-pax (system).
Source

chain.asd.

Child Components

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


3.1 Lisp


3.1.1 chain/chain.asd

Source

chain.asd.

Parent Component

chain (system).

ASDF Systems

chain.


3.1.2 chain/package.lisp

Source

chain.asd.

Parent Component

chain (system).

Packages

chain.

Internals

3.1.3 chain/chain.lisp

Dependency

package.lisp (file).

Source

chain.asd.

Parent Component

chain (system).

Public Interface
Internals

4 Packages

Packages are listed by definition order.


4.1 chain

Source

package.lisp.

Use List
  • common-lisp.
  • metabang.bind.
  • mgl-pax.
Public Interface
Internals

5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


5.1 Public Interface


5.1.1 Macros

Macro: => (argument &body body)

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.
“‘

Package

chain.

Source

chain.lisp.

Macro: def+> (name (main-arg &rest args) &body body)

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.

Package

chain.

Source

chain.lisp.

Macro: def=> (name &body body)

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
“‘

Package

chain.

Source

chain.lisp.

Macro: lambda+> ((main-arg &rest args) &body body)

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.

Package

chain.

Source

chain.lisp.

Macro: lambda=> (&body body)

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
“‘

Package

chain.

Source

chain.lisp.

Macro: set=> (argument &body body)

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
“‘

Package

chain.

Source

chain.lisp.


5.2 Internals


5.2.1 Special variables

Special Variable: @chain
Package

chain.

Source

package.lisp.

Special Variable: @reference
Package

chain.

Source

package.lisp.


5.2.2 Macros

Macro: chop (var list &body body)
Package

chain.

Source

chain.lisp.


5.2.3 Ordinary functions

Function: expand-chain (form forms inner-block-name outer-block-name &optional n)
Package

chain.

Source

chain.lisp.

Function: value-form (form later?)
Package

chain.

Source

chain.lisp.

Function: write-readme ()
Package

chain.

Source

package.lisp.


Appendix A Indexes


A.1 Concepts