;; A Co-Routine Example. ;; If you're a C programmer, you might find this explanation easier: in ;; C, you can take a pointer to a function. In C, you also have a return ;; statement. Suppose the return statement were a function (which never ;; returned, of course). It would take a parameter of the same type as ;; the return type of the function it was returning from. Now suppose you ;; could take its address. You could store that address in a variable or ;; pass it as a parameter, and allow functions to return on your ;; behalf. That's what CallWithCurrentContinuation allows you to do. You ;; can use it as a replacement for throw and catch, or you can set up ;; coroutines with it. -- EdwardKiser ;; Today's programs typically are objects; they have a member function ;; which the OS calls when a key is pressed. Old programs used to be ;; able to call a "get key" function to get a key from the OS. ;; You can write a "get key" function using co-routines. Co-routines ;; can be set up with multiple threads (see WindowThreadControlThread), ;; with some kind of virtual machine (see RunAndReturnSuccessor), or ;; with CallWithCurrentContinuation. ;; Here's an example of how you would do it in the SchemeLanguage. ;; First, you have the analogous function to "get-key." Here I will ;; allow it to call Scheme's (read) function and get an entire value. (define get-value (lambda (prompt) (display prompt) (newline) (read))) ;; Then you can create windows that take their "get-value" function as ;; a parameter. Here's a way to create such windows: (define create-window-for-function (lambda (function name) (lambda (get-value) (let* ((first (get-value (string-append "Type first number for " name))) (second (get-value (string-append "Type second number for " name)))) (function first second))))) ;; Now you can have conversations with the interpreter like this (where ;; OK is the "unspecified" value): ;; > (define win (create-window-for-function + "plus")) ;; OK ;; > (win get-value) ;; Type first number for plus ;; 4 ;; Type second number for plus ;; 8 ;; 12 ;; > ;; So far, lest you be confused, this has nothing to do with ;; continuation passing; it's just ordinary FunctionalProgramming. ;; Now, wouldn't it be neat if you could "invert" one of these windows? ;; If you could make it so that, instead of being a function that stops ;; and calls get-value to get an answer from you, it waits like an ;; object for you to provide a value to it, and provides a member ;; function you can use to provide that value? You can. Watch this: (define invert-window (lambda (window))) (call-with-current-continuation (lambda (first-return))) (let* ((return first-return) (windowval (window (lambda (prompt) (call-with-current-continuation (lambda (send) (return (list prompt (lambda (value) (call-with-current-continuation (lambda (new-return) (set! return new-return) (send value)))))))))))) (return windowval)) ;; Now you can have a conversation like this: ;; > (define iwin (invert-window win)) ;; OK ;; > iwin ;; ("Type first number for plus" #) ;; > (set! iwin ((cadr iwin) 12)) ;; OK ;; > iwin ;; ("Type second number for plus" #) ;; > (set! iwin ((cadr iwin) 24)) ;; OK ;; > iwin ;; 36 ;; As you can see, the window basically presented itself as an object. Its ;; latest prompt was part of its state, and it provided a function by which I ;; could send in an answer. I have turned it into a co-routine! ;; The same kind of thing can be done under program control. ;; -- EdwardKiser