Please take a look at two-in-a-row*?
function in chapter 19.
My question is about the (leave '())
in the get-first
helper function. Note that (waddle l)
will either return '()
or an atom, which indicates the list has exhausted or an atom from the list is retrieved.
Without (leave '())
it will still return those two kinds of values, just not use the continuation leave
. But the book says without (leave '())
is bad, I just can not see why.
(define two-in-a-row*
(letrec ([leave id] ; the identity function
[fill id]
[waddle (lambda (l)
(cond [(null? l) '()]
[(atom? (car l))
(begin
(letcc rest
(set! fill rest)
(leave (car l)))
(waddle (cdr l)))]
[else
(begin
(waddle (car l))
(waddle (cdr l)))]))]
[get-first (lambda (l)
(letcc here
(set! leave here)
(waddle l)
(leave '()) ; why is this part needed???
))]
[get-next (lambda (l)
(letcc here
(set! leave here)
(fill 'go)))]
[T? (lambda (a)
(let ([n (get-next 'dummy)])
(if (atom? n)
(or (eq? a n)
(T? n))
#f)))])
(lambda (l)
(let ([fst (get-first l)])
(if (atom? fst)
(T? fst)
#f)))))
Thanks very much.
Another interesting tread about this problem.
So thanks for Will Ness's examples. I went over some even simpler ones. So "what is it so bad about that?" -- without (leave '())
in get-first
.
Short Answer:
Note that from my code
i) leave
will always be recreated each time when we call get-first
or get-next
. It will return to either get-first
or get-next
.
ii) fill
will result to be a chain depending on previous fill
, and it will always return to get-first
.
Example
Input: '(1)
So we start by evaluating get-first
on '(1)
.
i) set leave
ii) start (waddle '(1)
iii) since 1
is an atom, so set fill
to be current continuation. Note if we use fill
, then it will go to do (waddle (cdr l))
, then it will return to get-first
.
iv) return to get-first
by using leave
with return value 1
.
Then we go to eval (T? 1)
, which will in turn go to run get-next
.
i) set leave
ii) run fill
iii) start (waddle '())
iv) return ()
from waddle
, then return to get-first
.
Note
1) If we don't have (leave '()
, then get-first
will return '()
, then the two-in-a-row*
return #f
. So we can get the same answer, but the behavior is not what we want.
2) If we have it, then note that leave
is now the leave
created by get-next
, thus it is going to transfer '()
to get-next
.
3) With more than 1 input in the list when we create fill
it will be created based on previous fill
, thus result to be a chain depending previous fill
.