The following syntax can be obtained with
(use-modules (srfi srfi-2))
or alternatively
(use-modules (ice-9 and-let-star))
A combination of and
and let*
.
Each clause is evaluated in turn, and if #f
is obtained
then evaluation stops and #f
is returned. If all are
non-#f
then body is evaluated and the last form gives the
return value, or if body is empty then the result is #t
.
Each clause should be one of the following,
(symbol expr)
Evaluate expr, check for #f
, and bind it to symbol.
Like let*
, that binding is available to subsequent clauses.
(expr)
Evaluate expr and check for #f
.
symbol
Get the value bound to symbol and check for #f
.
Notice that (expr)
has an “extra” pair of parentheses, for
instance ((eq? x y))
. One way to remember this is to imagine
the symbol
in (symbol expr)
is omitted.
and-let*
is good for calculations where a #f
value means
termination, but where a non-#f
value is going to be needed in
subsequent expressions.
The following illustrates this, it returns text between brackets
‘[...]’ in a string, or #f
if there are no such brackets
(ie. either string-index
gives #f
).
(define (extract-brackets str) (and-let* ((start (string-index str #\[)) (end (string-index str #\] start))) (substring str (1+ start) end)))
The following shows plain variables and expressions tested too.
diagnostic-levels
is taken to be an alist associating a
diagnostic type with a level. str
is printed only if the type
is known and its level is high enough.
(define (show-diagnostic type str) (and-let* (want-diagnostics (level (assq-ref diagnostic-levels type)) ((>= level current-diagnostic-level))) (display str)))
The advantage of and-let*
is that an extended sequence of
expressions and tests doesn’t require lots of nesting as would arise
from separate and
and let*
, or from cond
with
=>
.