;;; File: ;;; webcont.scm ;;; Author: ;;; Samuel A. Rebelsky ;;; Summary: ;;; A quick-and-dirty collection of code to illustrate how one might ;;; use continuations to implement a stateful system on the Web. ;;; The code is intentionally undercommented. ;;; Usage: ;;; For a really silly program, run (silly). It will prompt you ;;; for an operation (Should be add or square) and then for the ;;; values. ;;; To simulate what might happen on the Web (with continuations), ;;; run (web) and then (silly). You will see a line that looks like ;;; [c###] Please enter an operation. You will then return to the ;;; command line. To resume any point of computation, type ;;; (resume 'c#### RESPONSE) ;;; where RESPONSE is 'add or 'square (for the first prompt) and ;;; a number (for any other prompt). ;;; Bug: ;;; The top-level exit-continuation is not defined quite right. ;;; URL: ;;; http://www.cs.grinnell.edu/~rebelsky/Courses/CS302/2007S/Examples/webcont.scm ;;; Version: ;;; 1.1 of 26 February 2007 (define stored-continuations null) (define exit null) (define set-exit! (lambda () (let/cc k (set! exit k)))) (define remember (lambda (cont) (let ((cid (string->symbol (string-append "c" (number->string (random 1000)))))) (set! stored-continuations (cons (cons cid cont) stored-continuations)) cid))) (define recall (lambda (cid) (cdr (assoc cid stored-continuations)))) (define resume (lambda (cid val) ((recall cid) val))) (define local-prompt (lambda (prompt) (display prompt) (read))) (define local-result (lambda (result) (display result) (newline))) (define web-prompt (lambda (prompt) (let/cc k ; Generate a name for the continuation that we ; can use later. (let ((cont (remember k))) ; Code to build a Web page simulated (display "[") (display cont) (display "] ") (display prompt) (newline)) ; That's it (exit)))) (define web-result (lambda (result) (display "
") (display result) (display "
") (newline))) (define prompt local-prompt) (define result local-result) (define local (lambda () (set! prompt local-prompt) (set! result local-result))) (define web (lambda () (set! prompt web-prompt) (set! result web-result))) (define silly (lambda () (let ((op (prompt "Please enter the desired operation "))) (cond ((eq? op 'square) (let ((val (prompt "Please enter a number "))) (result (* val val)))) ((eq? op 'add) (let* ((left (prompt "Please enter a number ")) (right (prompt "Please enter another number "))) (result (+ left right)))) (else (result "Invalid operation.") (silly)) ) ) ) ) (set-exit!)