(call-with-current-continuation (lambda (return) (begin (display "One ") (return #t) (display "Two ") #f)))
In the above example, it would print "One ", and bail out by returning the value #t. The remainder of the lambda is never executed. Note that 'return' is a paramater, so you could choose whatever name you wanted to.
It is useful to have some syntactic sugar for the above. A standard name is 'let-cc', defined as follows:
(define-syntax let-cc (syntax-rules () ((let-cc variable . body) (call-with-current-continuation (lambda (variable) . body)))))
I can then type things more conveniently:
(let-cc return (display "One ") (return #t) (display "Two ") #f)
Note that my choice of use of the word 'return' is still arbitrary. It's very flexible, because I can have any number of 'named' blocked, and return to whatever part of the program I am interested in.
Suppose I want to give up some flexibility, and that I want 'return' to be part of my syntax. I want a block/return (similar to Lisp's block nil) construction. 'return' means that I want to return from the block. To put it in more concrete terms, I want to be able to write:
(block (write-line "this is printed") (return "this is returned") (write-line "this is never printed"))
A macro which satisfies this is:
(define-syntax block (lambda (x r c) (let ((body (cdr x))) `(call-with-current-continuation (lambda (return) ,@body)))))
The above was written for Chicken Scheme. Other Schemes might not support it - it's certainly do-able in other schemes - but the implementation might be rather hairier (check out the cls link below, for example).
Further reading:
- comp.lang.scheme - discussion on writing block/return macros, started by me
- Wikipedia - discusses continuations, and how you might write a Pythonesque 'yield' statement
- Hygenic macros - a discussion
- Chicken modules and macros - Reference documentation for Chicken v4.x
No comments:
Post a Comment