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 '())inget-first.Short Answer:
Note that from my code
i)
leavewill always be recreated each time when we callget-firstorget-next. It will return to eitherget-firstorget-next.ii)
fillwill result to be a chain depending on previousfill, and it will always return toget-first.Example
Input:
'(1)So we start by evaluating
get-firston'(1).i) set
leaveii) start
(waddle '(1)iii) since
1is an atom, so setfillto be current continuation. Note if we usefill, then it will go to do(waddle (cdr l)), then it will return toget-first. iv) return toget-firstby usingleavewith return value1.Then we go to eval
(T? 1), which will in turn go to runget-next.i) set
leaveii) run
filliii) start
(waddle '())iv) return
()fromwaddle, then return toget-first.Note
1) If we don't have
(leave '(), thenget-firstwill return'(), then thetwo-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
leaveis now theleavecreated byget-next, thus it is going to transfer'()toget-next.3) With more than 1 input in the list when we create
fillit will be created based on previousfill, thus result to be a chain depending previousfill.