13 Continuations

advertisement
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
Download