;;; Call/cc examples ;;; From the R5RS Report: ;;; procedure: (call-with-current-continuation proc) ;;; proc must be a procedure of one argument. The procedure ;;; call-with-current-continuation packages up the current ;;; continuation (...) as an "escape procedure: and passes it ;;; as an argument to proc. The escape procedure is a Scheme ;;; procedure that, if it is later called, will abandon whatever ;;; continuation is in effect at that later time and will instead ;;; use the continuation that was in effect when the escape procedure ;;; was created. (define call/cc call-with-current-continuation) ;;; R5RS examples (call/cc (lambda (exit) (define (loop nums) (if (null? nums) #t (if (< (car nums) 0) (exit (car nums)) (loop (cdr nums))))) (loop '(54 0 37 -3 247 15)))) ;;; ==> -3 (define (list-length obj) (call/cc (lambda (return) (define (loop obj) (if (null? obj) 0 (if (pair? obj) (+ (loop (cdr obj)) 1) (return '#f)))) (loop obj)))) (list-length '(1 2 3)) ;;; ==> 3 (list-length '(1 2 3 . 4)) ;;; ==> #f ;;; TSPL3 examples (call/cc (lambda (k) (* 5 4))) ;;; ==> 20 (call/cc (lambda (k) (* 5 (k 4)))) ;;; ==> 4 (+ 2 (call/cc (lambda (k) (* 5 (k 4))))) ;;; ==> 6 (define memberq (lambda (x ls) (call/cc (lambda (break) (do ((ls ls (cdr ls))) ((null? ls) #f) (if (equal? x (car ls)) (break ls))))))) (memberq 'd '(a b c)) ;;; ==>?#f (memberq 'b '(a b c)) ;;; ==> (b c) (define productx (lambda (ls) (call/cc (lambda (break) (let f ((ls ls)) (cond ((null? ls) 1) ((= (car ls) 0) (break 0)) (else (* (car ls) (f (cdr ls)))))))))) (productx '(1 2 3 4 5)) ;;; ==> 120 (productx '(7 3 8 0 1 9 5)) ;;; ==> 0 (let ((x (call/cc (lambda (k) k)))) (x (lambda (ignore) "hi"))) ;;; ==> "hi" ;;; The continuation obtained by this invocation of call/cc may be described as ;;; "Take the value, bind it to x, and apply the value of x to the value of ;;; (lambda (ignore) "hi")." Since (lambda (k) k) returns its argument, x is ;;; bound to the continuation itself; this continuation is applied to the ;;; procedure resulting from the evaluation of (lambda (ignore) "hi"). This ;;; has the effect of binding x (again!) to this procedure and applying the ;;; procedure to itself. The procedure ignores its argument and returns "hi". ((lambda (x) (x (lambda (ignore) "hi"))) (call/cc (lambda (k) k))) (((call/cc (lambda (k) k)) (lambda (x) x)) "HEY!") ;;; ==> "HEY!"