Programming Languages Chapter 19 - Continuations Dr. Philip Cannata 1 Exceptions (define (f n) (let/cc esc (/ 1 (if (zero? n) (esc 1) n)))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (f 0) 1 > (f 2) 1/2 > (f 1) 1 > Dr. Philip Cannata 2 Exceptions (define (f n) (let/cc esc (/ 1 (if (zero? n) (esc 1) n)))) When you invoke the continuation, it’s as if the entire let/cc expression that binds esc should be cut out of the program and replaced with the value passed to esc, i.e., its as if the actual code for f is really this: (define (f n) 1) Dr. Philip Cannata 3 Escaping Procedures (define (f n) (+ n (let/cc k (- 5 (k 5))))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (f 6) 11 > Dr. Philip Cannata 4 Producers and Consumers (define route-producer (local ([define resume (box false)]) (lambda (real-send) (local ([define send (lambda (value-to-send) (let/cc k (begin (set-box! k) We’llresume see these (real-send value-to-send))))]) details in a few slides (if (unbox resume) ((unbox resume) 'dummy) (begin (send 'providence) (send 'houston) (send 'bangalore))))))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (let/cc k (route-producer k)) 'providence > (let/cc k (route-producer k)) 'houston > (let/cc k (route-producer k)) 'bangalore > (let/cc k (route-producer k)) 'dummy Dr. Philip Cannata 5 Producers and Consumers – Oracle sequence example CREATE TABLE EMP (EMPNO NUMBER(7) NOT NULL, CONSTRAINT emp_pkey PRIMARY KEY (empno), ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7, 2), COMM NUMBER(7, 2), DEPTNO NUMBER(2)); drop sequence emp_empno; create sequence emp_empno start with 1 increment by 1 nomaxvalue; create or replace trigger emp_empno_trigger before insert on emp for each row begin select emp_empno.nextval into :new.empno from dual; end; INSERT INTO EMP VALUES (7369, 'SMITH', 'CLERK', 7902, TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20); INSERT INTO EMP VALUES (7499, 'ALLEN', 'SALESMAN', 7698, TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30); INSERT INTO EMP VALUES (7521, 'WARD', 'SALESMAN', 7698, TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30); INSERT INTO EMP VALUES (7566, 'JONES', 'MANAGER', 7839, TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20); INSERT INTO EMP VALUES (7654, 'MARTIN', 'SALESMAN', 7698, TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30); INSERT INTO EMP VALUES (7698, 'BLAKE', 'MANAGER', 7839, TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30); INSERT INTO EMP VALUES (7782, 'CLARK', 'MANAGER', 7839, TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10); INSERT INTO EMP VALUES (7788, 'SCOTT', 'ANALYST', 7566, TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES (7839, 'KING', 'PRESIDENT', NULL, TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10); INSERT INTO EMP VALUES (7844, 'TURNER', 'SALESMAN', 7698, TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, NULL, 30); INSERT INTO EMP VALUES (7876, 'ADAMS', 'CLERK', 7788, TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20); INSERT INTO EMP VALUES (7900, 'JAMES', 'CLERK', 7698, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30); INSERT INTO EMP VALUES (7902, 'FORD', 'ANALYST', 7566, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES (7934, 'MILLER', 'CLERK', 7782, TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10); Dr. Philip Cannata 6 Producers and Consumers – Oracle sequence example Dr. Philip Cannata 7 Continuations (define (f n) (let/cc esc (/ 1 (if (zero? n) (esc 1) n)))) 1. When you invoke the continuation, it’s as if the entire let/cc expression that binds esc should be cut out of the program and replaced with the value passed to esc, i.e., its as if the actual code for f is really this: (define (f n) 1) 2. let/cc binds its variable to the next sexp when it is invoked. 3. let/cc causes the interpreter to revert to the state that it was in when the let/cc was defined when the let/cc variable is invoked. Dr. Philip Cannata 8 Producers and Consumers (define (route-producer send) (begin (send 'providence) (send 'houston) (send 'bangalore))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (route-producer display) providencehoustonbangalore > (let/cc k (route-producer k)) 'providence > (let/cc k (route-producer k)) 'providence Dr. Philip Cannata 9 Producers and Consumers (define route-producer (local ([define resume (box false)]) (lambda (send) (if (unbox resume) ((unbox resume) 'dummy) (begin (send 'providence) (send 'houston) (send 'bangalore)))))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (let/cc k (route-producer k)) 'providence > (let/cc k (route-producer k)) 'providence Dr. Philip Cannata 10 Producers and Consumers (define route-producer (local ([define resume (box false)]) (lambda (send) (if (unbox resume) ((unbox resume) 'dummy) (begin (send (unbox resume)) (send 'houston) (send 'bangalore)))))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (let/cc k (route-producer k)) false > Dr. Philip Cannata 11 Producers and Consumers (define route-producer (local ([define resume (box false)]) (lambda (real-send) (local ([define send (lambda (value-to-send) (let/cc k (begin (set-box! resume k) (real-send value-to-send))))]) (if (unbox resume) ((unbox resume) 'dummy) (begin (send 'providence) (send 'houston) (send 'bangalore))))))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (let/cc q (route-producer q)) 'providence > (let/cc q (route-producer q)) 'houston > (let/cc q (route-producer q)) 'bangalore > (let/cc q (route-producer q)) 'dummy Dr. Philip Cannata 12 Producers and Consumers (define route-producer (local ([define resume (box false)]) (lambda (real-send) (local ([define send (lambda (value-to-send) (let/cc k (begin (set-box! resume k) (real-send value-to-send))))]) (if (unbox resume) ((unbox resume) 'dummy) (begin (send 'providence) (send 'houston) (send 'bangalore))))))) Welcome to DrScheme, version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. > (route-producer display) providencehoustonbangalore > (route-producer display) 'dummy > (route-producer display) 'dummy Dr. Philip Cannata 13 Producers and Consumers (define route-producer (local ([define resume (box false)]) (lambda (real-send) (local ([define send (lambda (value-to-send) (let/cc k (begin (set-box! resume k) (real-send value-to-send))))]) (if (unbox resume) ((unbox resume) 'dummy) (begin (send 'providence) (send 'houston) (send 'bangalore))))))) Welcome to DrScheme, version 4.2.1 [3m]. Run 1. and then run 2. Language: PLAI Scheme; memory limit: 256 megabytes. > (let/cc q (route-producer q)) Then restart and just run 2. 'providence 1. What will this do? > (let/cc q (route-producer q)) (let ((a 1)) (display (let/cc q (route-producer q))) (display a) (display " ") 'houston (let ((a 2)) (display a))) > (let/cc q (route-producer q)) 2. What will this do? (let ((a 1)) (display (let/cc q (route-producer q))) (display a) (display " ") 'bangalore (let ((a 2)) (route-producer display) (display a))) > (let/cc q (route-producer q)) 'dummy Dr. Philip Cannata 14 Producers and Consumers (define (make-producer body) (define resume (box false)) (lambda (real-send) (define send-to (box real-send)) (define (send value-to-send) (set-box! send-to (let/cc k (begin (set-box! resume k) ((unbox send-to) value-to-send))))) (if (unbox resume) ((unbox resume) real-send) (body send)))) (define number-producer (make-producer (lambda (send) (begin (send 1) (send 2) (send 3))))) (define get call/cc) press “Run” > (+ (get number-producer) (get number-producer) (get number-producer) ) 6 > press “Run” > (+ (get number-producer) (get number-producer) (get number-producer) (get number-producer)) . . user break > (get number-producer) Dr. Philip Cannata 15 Producers and Consumers (define (make-producer body) (define resume (box false)) (lambda (real-send) (define send-to (box real-send)) (define (send value-to-send) (set-box! send-to (let/cc k (begin (set-box! resume k) ((unbox send-to) value-to-send))))) (if (unbox resume) ((unbox resume) real-send) (body send)))) press “Run” > (+ (get odds-producer) (get odds-producer) (get odds-producer) (get odds-producer) (get odds-producer)) 25 > (define (odds-producer-body send) (local ([define (loop n) (begin (send n) (loop (+ n 2)))]) (loop 1))) (define odds-producer (make-producer odds-producer-body)) (define (get producer) (let/cc k (producer k))) Dr. Philip Cannata 16 Producers and Consumers (define (make-producer body) (define resume (box false)) (lambda (real-send) (define send-to (box real-send)) (define (send value-to-send) (set-box! send-to (let/cc k (begin (set-box! resume k) ((unbox send-to) value-to-send))))) (if (unbox resume) ((unbox resume) real-send) (body send)))) (define (integer-producer-body send) (local ([define (loop n) (begin (send n) (loop (+ n 1)))]) (loop 1))) (define integer-producer (make-producer integer-producer-body)) (define (get producer) (let/cc k (producer k))) (define (Loop n) (define integer-producer (make-producer integer-producer-body)) (define List (box (list))) (let y ((x n)) (set-box! List (cons (get integer-producer) (unbox List ))) (if (> x 1) (y (- x 1) ) (begin (display (unbox List)) (newline) (eval (cons '* (unbox List))))))) Dr. Philip Cannata 17