Reputation: 11197
On page 66 of "The Seasoned Schemer" it says that (let ...)
is an abbreviation for :
(let ((x1 a1) ... (xn an)) b ...) = ((lambda (x1 ... xn) b ...) a1 ... an)
Its used on for example on page 70:
(define depth*
(lambda (l)
(let ((a (add1 (depth* (car l))))
(d (depth* (cdr l))))
(cond
((null? l) 1)
((atom? (car l)) d)
(else (cond
((> d a) d)
(else a)))))))
But that above definition of lambda
would suggest that (add1 (depth* (car l))
and (depth* (cdr l))
are evaluated and passed into the lambda represented by (lambda (x1 ... xn) b ...)
. But this would mean that the list l
, which could potentially be empty, would be passed to car
and cdr
before the null check in (null? l) 1)
is ever done.
Upvotes: 3
Views: 109
Reputation: 236150
You're right in stating that (car l)
and (cdr l)
will get executed before testing if l
is null, therefore raising an error if l
is indeed null
. Keep reading the book, in the following two pages this is explained, and a correct version of depth*
is shown.
Upvotes: 3
Reputation: 70245
The let
syntactic keyword accepts the following form (ignore 'named-let'):
(define-syntax let
(syntax-rules ()
((let ((identifier expression) ...) body ...)
;; ...)))
At the point where let
is used each of expression ...
is evaluated. The expressions are evaluated in an unspecified order.
In your case, the expressions for a
and d
involving depth*
will be evaluated before the body. Thus, as you've concluded, l
could be '()
when car
and cdr
are invoked.
Upvotes: 0