Reputation: 2239
In this code
(defun foo ()
. . .
(let ((bar (foo)))
(if bar
. . .)))
in the let
line, let
is only binding, right? It doesn't actually run foo
. I assume foo
is run (recursively) for the first time in the if
statement, correct? If what I assume is correct, is there a way to have let
actually execute foo
and then assign the results to bar
?
Upvotes: 1
Views: 99
Reputation: 85813
There's an answer that shows an example that illustrates the behavior of let. However, an example via an implementation doesn't answer conclusively whether it's supposed to behave that way, or whether implementations are free to do different things, or whether there's a bug in the implementation. To know what's supposed to happen, you need to check the documentation. Fortunately, the Common Lisp HyperSpec is freely available online. The documentation for let says:
Special Operator LET, LET*
let and let* create new variable bindings and execute a series of forms that use these bindings. let performs the bindings in parallel and let* does them sequentially.
The form
(let ((var1 init-form-1) (var2 init-form-2) ... (varm init-form-m)) declaration1 declaration2 ... declarationp form1 form2 ... formn)
first evaluates the expressions init-form-1, init-form-2, and so on, in that order, saving the resulting values. Then all of the variables varj are bound to the corresponding values; each binding is lexical unless there is a special declaration to the contrary. The expressions formk are then evaluated in order; the values of all but the last are discarded (that is, the body of a let is an implicit progn).
Thus, all the forms are evaluated (executed), then the results are bound the values, and then the forms in the body are evaluated.
Upvotes: 5
Reputation: 618
In the example you provided, foo
is evaluated and then assigned to bar
. You can test this by simply evaluating something like:
(let ((foo (+ 1 2)))
(if (= foo 3)
foo
nil))
; => 3
cf. PCL: Syntax and Semantics or Lispdoc.
As @paulo-madeira brought up in the comments, this is not enough to test, since you don't know when each one was evaluated. See his comment for a way to test it using FORMAT
. Anyway, the takeaway is, the LET
you propose evaluates foo
and assigns it to bar
, which means your function foo
is defined in terms of itself, which means you're up to no good.
Upvotes: 2