the informal ramblings of a formal language researcher

Tuesday, August 25, 2009

yet another yield Scheme macro

I have seen yield done plenty of times before, but I managed to reinvent it again tonight.

A lot of the time when I've played with call/cc, I have approached it trying to recreate a form in a statement-oriented language, and so I would end up not caring about the argument I would pass to the invocation of the captured continuation (because all I cared about was reestablishing the control flow of the prior context; the prior context itself would just discard any value I passed to it). I think the usual interpretation of yield is an instance of this in statement oriented languages.

However, when I was playing with some code tonight, I saw that dummy value and said, "ugly! why is that there?" And I decided to see what would happen if I got rid of it.

This macro is the result. (Obviously you want a bit of sugar around it to non-hygenically bind yield, although there are cases where it is nice to bind a different name like visit instead of yield, depending on the domain.)


(define-syntax generator-via
(syntax-rules ()
;; puzzle 4 U: what role(s) does arg-list serve? (all occurrences matter)
((generator-via yield-id arg-list body ...)
(let ((yield-id #f) (get-next #f))
(lambda arg-list
(call-with-current-continuation
(lambda (exit)
(cond (get-next (get-next exit . arg-list))
(else (set! yield-id (lambda results
(call-with-current-continuation
(lambda (next)
(set! get-next
(lambda (new-exit . arg-list)
(set! exit new-exit)
(next . arg-list)))
(apply exit results)))))
(call-with-values (lambda () body ...)
;; puzzle 4 U: why below eta-expansion required?
(lambda args (apply exit args))))))))))))


Its got some fun behaviors. Consider:


> (define grows
(generator-via yield (x)
(let loop ((i 0))
(loop (+ i x (yield i))))))

> (grows 1)
0

> (grows 0)
1

> (grows 0)
2

> (grows 0)
3

> (grows 1)
5

> (grows 0)
6



(yes I just realized I could/should have let-bound the yield-id itself. The other set! invocations are believed to be necessary, barring tricks mixing letrec and call/cc.)

No comments:

Followers