(define damn (lambda () (call/cc (lambda (k) (cons (cons 'side-effect 'bad) (k 'id))))))
-The idea here is we capture the continuation that `(damn)` has when it gets evaluated. This continuation is bound to the variable `k`. We supply `'id` as an argument to that continuation. When the main, at-issue tree is all built, then we return a pair `'((side-effect bad) AT-ISSUE-TREE)`.
+The idea here is we capture the continuation that `(damn)` has when it gets evaluated. This continuation is bound to the variable `k`. We supply `'id` as an argument to that continuation. When the main, at-issue tree is all built, then we return a pair `'((side-effect . bad) AT-ISSUE-TREE)`.
However, this doesn't work. The reason is that an undelimited continuation represents the future of the evaluation of `(damn)` *until the end of the computation*. So when `'id` is supplied to `k`, we go back to building the at-issue tree until we're finished *and that's the end of the computation*. We never get to go back and evaluate the application of `(cons (cons 'side-effect 'bad) <>)` to anything.
And voila:
-(reset (cons (cons 'the 'man)
- (cons 'read
- (cons 'the
- (cons (damn)
- 'book)))))
+ (reset (cons (cons 'the 'man)
+ (cons 'read
+ (cons 'the
+ (cons (damn)
+ 'book)))))
evaluates to:
- '((side-effect bad) ((the . man) . (read . (the . (id . book)))))
+ '((side-effect . bad) ((the . man) . (read . (the . (id . book)))))
So that's the straightforward way of repairing the strategy we used in class, without using `print`. We also have to switch to using delimited continuations.
Ken Shan pointed out a lovely way to get to the same end-point still using only undelimited continuations (`call/cc`).
-(let ((pragma
- ; An ordered pair whose first component is the assertion
- ; operator, a unary function, and whose second component
- ; is the meaning of "damn", a thunk.
- (call/cc (lambda (k)
- (cons (lambda (p) p)
- (lambda () (k (cons (lambda (p) (cons (cons 'side-effect 'bad) p))
- (lambda () 'id)))))))))
- (let ((assert (car pragma)) ; this binds assert to the first element of the pair pragma
- (damn (cdr pragma))) ; this binds damn to the second element of the pair pragma
- (assert (cons (cons 'the 'student) (cons 'read (cons 'the (cons (damn) 'book)))))))
+ (let ((pragma
+ ; An ordered pair whose first component is the assertion
+ ; operator, a unary function, and whose second component
+ ; is the meaning of "damn", a thunk.
+ (call/cc (lambda (k)
+ (cons (lambda (p) p)
+ (lambda () (k (cons (lambda (p) (cons (cons 'side-effect 'bad) p))
+ (lambda () 'id)))))))))
+ (let ((assert (car pragma)) ; this binds assert to the first element of the pair pragma
+ (damn (cdr pragma))) ; this binds damn to the second element of the pair pragma
+ (assert (cons (cons 'the 'student) (cons 'read (cons 'the (cons (damn) 'book)))))))
We won't do much to explain this. We'll just leave it for you to chew on.