The case against IF-LET*
Michał "phoe" Herda · Monday, 15 April, 2019 - 11:49 edit · 1 minute
Someone asked a question on
#lisp on Freenode: since
WHEN-LET has an analogous
IF-LET has no analogous
Here is my attempt at answering it.
Suppose we have a following code block:
(if-let ((x 42) (y nil) (z :foo)) (list :true x y z) (list :false x y z))
Z are bound to the respective values:
:FOO. At least one of the values
is false. Therefore, it should be obvious that the result of evaluating this code would be the list
(:FALSE 42 NIL :FOO).
Now, let us slightly modify this code:
(if-let* ((x 42) (y nil) (z :foo)) (list :true x y z) (list :false x y z))
We no longer use
IF-LET but instead we use the hypothetical sequential version,
IF-LET*. We evaluate
By definition, we are supposed to not evaluate the following variables at this moment, since
Y evaluated to false,
and we instead execute the false branch.
The big question is: what is the value of
Z in the false branch?
It is certainly not
:FOO because we have not managed to evaluate that binding yet. In fact, that lexical variable
should be unbound since there is no logical value for it, but there is no such thing as an unbound lexical variable in Lisp.
In particular, this might mean that we encounter any number of logically unbound variables in the false branch.
We could work around it by setting the not-yet-bound lexical variables to some predefined value (which would
greatly complicate the code and introduce a lot of mess) or we would make the false branch unable to use any of the lexical
bindings, which makes the sequential
IF-LET* greatly inconsistent with the parallel
In other words: having
IF-LET* would be inconsistent. None of the variables are available in the lexical scope of the false branch, and that should be part of