Seasoned Schemer's get-first, get-next, and wa

2019-05-03 14:17发布

问题:

(define get-first
  (lambda (l)
    (call-with-current-continuation
      (lambda (here)
        (set! leave here)
        (waddle l)
        (leave (quote ()))))))

(define get-first
  (lambda (l)
    (call-with-current-continuation
      (lambda (here)
        (set! leave here)
        (leave (waddle l))))))

For anybody not familiar with the book "The Seasoned Schemer", get-first, get-next, and waddle (last two not defined here) are procedures to apparently model coroutines to iterate through a tree passed to waddle that yields leaves only. Just prior to waddle's yield on its second-to-last re-entry, it sets the re-entry point to where it will only ever return the pure value '() i.e. instead of yielding '() , the actual value of waddle is '() , as if it were a pure function all along.

With this in mind, we can see what get-first sets up... When waddle returns "for real", it will be inside the call/cc in get-first and then (leave (quote ())) is the value of get-first (and, in turn, this leave is intended to return to get-next on the last iteration, therefore it is get-next that does the "actual" return of '()).

So why is the second version not equivalent, where waddle's value of '() would be the argument to leave?

回答1:

The confusion is because "leave" is not the function I want it to be, but the function it evaluates to when it's evaluated, which appears to be left-to-right and thus before "waddle". That means it evaluates to what it was just set to, in the statement prior.

Moral: beware when using functions that are subject to redefining WITHIN the call to the function! If this was on a right-to-left interpreter, waddle would be evaluated before the symbol leave was looked up as the function that "leaves" to wherever, during which time it would be set to a DIFFERENT function.