The Urn Logo


(if-let vars then else)

Macro defined at lib/core/binders.lisp:134:2

Evaluate THEN or ELSE, depending on the truthiness of all variables bound (as per let) in VARS.


> (if-let [(a 1)
.          (b false)]
.   b
.   a)
out = 1

(if-with var then else)

Macro defined at lib/core/binders.lisp:152:2

Bind the pair VAR of the form (name value), evaluating THEN if the value is truthy or ELSE if not.


> (if-with ((a b c) (values-list false 1 2))
.   a
.   (+ b c))
out = 3

(let vars &body)

Macro defined at lib/core/binders.lisp:55:2

Bind several variables (given in VARS), then evaluate BODY. In contrast to let*, variables bound with let can not refer to each other.


> (let [(foo 1)
.       (bar 2)]
.   (+ foo bar))
out = 3

(let* vars &body)

Macro defined at lib/core/binders.lisp:30:2

Bind several variables (given in VARS), then evaluate BODY. Variables bound with let* can refer to variables bound previously, as they are evaluated in order.


> (let* [(foo 1)
.        (bar (+ foo 1))]
.   bar)
out = 2

(letrec vars &body)

Macro defined at lib/core/binders.lisp:177:2

Bind several variables (given in VARS), which may be recursive.


> (letrec [(is-even? (lambda (n)
.                        (or (= 0 n)
.                            (is-odd? (pred n)))))
.            (is-odd? (lambda (n)
.                       (and (not (= 0 n))
.                            (is-even? (pred n)))))]
.     (is-odd? 11))
out = true

(loop vs test &body)

Macro defined at lib/core/binders.lisp:225:2

A general iteration helper.

> (loop [(var0 val0)
.        (var1 val1)
.        ...]
.   [test test-body ...]
.   body ...)

Bind all the variables given in VS. Each iteration begins by evaluating TEST. If it evaluates to a truthy value, TEST-BODY is evaluated and the final expression in TEST-BODY is returned. In the case that TEST is falsey, the set of expressions BODY is evaluated. BODY may contain the “magic” form (recur val0 val1 ...), which rebinds the respective variables in VS and reiterates.


> (loop [(o '())
.        (l '(1 2 3))]
.   [(empty? l) o]
.   (recur (cons (car l) o) (cdr l)))
out = (3 2 1)

(use var &body)

Macro defined at lib/core/binders.lisp:201:2

Bind each variable in VAR, checking for truthyness between bindings, execute BODY, then run a finaliser for all the variables bound by VAR.

Potential finalisers might be:

  • (get-idx (getmetatable FOO) :--finalise), where FOO is the variable.
  • (get-idx FOO :close) where FOO is the variable.

If there is no finaliser for VAR, then nothing is done for it.


> (use [(file (io/open "tests/data/hello.txt"))]
.   (print! (self file :read "*a")))
Hello, world!
out = true

(when-let vars &body)

Macro defined at lib/core/binders.lisp:71:2

Bind VARS, as with let, and check they are all truthy before evaluating BODY.

> (when-let [(foo 1)
.            (bar nil)]
.   foo)
out = nil

Does not evaluate foo, while

> (when-let [(foo 1)
.            (bar 2)]
.   (+ foo bar))
out = 3


(when-let* vars &body)

Macro defined at lib/core/binders.lisp:93:2

Bind each pair of (name value) of VARS, checking if the value is truthy before binding the next, and finally evaluating BODY. As with let*, bindings inside when-let* can refer to previously bound names.


> (when-let* [(foo 1)
.             (bar nil)
.             (baz 2)]
.   (+ foo baz))
out = nil

Since 1 is truthy, it is evaluated and bound to foo, however, since nil is falsey, evaluation does not continue.

(when-with var &body)

Macro defined at lib/core/binders.lisp:118:2

Bind the PAIR var of the form (name value), only evaluating BODY if the value is truthy


> (when-with (foo (.> { :baz "foo" } :baz))
.   (print! foo))
out = nil

When bar has an index baz, it will be bound to foo and printed. If not, the print statement will not be executed.

(with var &body)

Macro defined at lib/core/binders.lisp:51:2

Bind the single variable VAR, then evaluate BODY.