代写代考 CSSE 304 Days 27 – 29

Laser Accent 1

CSSE 304 Days 27 – 29

Copyright By PowCoder代写 加微信 powcoder

Escape procedures
Call-with- procedures
Review continuations
Intro to call/cc
call/cc examples

Good and bad code for letrec

Springer/Friedman excerpt to read

Warm-up for call/cc
Escape procedures
Continuations

call/cc involves both receivers and escape
procedures, so we first define both of those.
Then we review continuations.

My discussion of call/cc is loosely based the book Scheme and the Art of Programming by and .

Review of Continuations
Consider the evaluation of the expression:
(let ([x (+ y 2)])
(if (< x 4) 5 (- x 6)) What is the continuation of 6 ? (+ y 2) ? (- x 6) ? (< x 4) I plan to go slow. Please don't let anything go over your head today. We can revisit anything! A receiver is an argument (which also happens to also be a procedure) passed to a procedure, with the intention that the procedure will eventually apply that receiver to some values; i.e. pass values to that receiver. Example: When we represent continuations by Scheme procedures, those continuations that we pass to CPS procedures are receivers. (lambda (v) …) They expect to receive a value for v. Sometimes receivers are called callbacks. Old Receiver Example: call-with-values > (call-with-values
(lambda () (values 3 4))
list is a receiver
(we previously called it the consumer)

new receiver example

(call-with-output-file “myfile.ss”
  (lambda (p) ; this is the “receiver”    
(let f ([ls list-to-be-printed])
      (if (not (null? ls))
            (write (car ls) p)
            (newline p)
            (f (cdr ls)))))))

From TSPL: The following shows the use of call-with-output-file to write a list of objects (the value of list-to-be-printed), separated by newlines, to the file named “myfile.ss.”

(define call-with-output-file
  (lambda (filename proc)
    (let ((p (open-output-file filename)))
      (let ((v (proc p)))
        (close-output-port p)
The receiver expects to receive an output port as its argument

An escape procedure
Pretend that we have a procedure escape-+ that adds its arguments and returns this sum as the final answer, no matter what the context.
(* (escape‑+ 5 6) 3) 
(escape-+ (escape-+ 2 4) 5) 

We can say that escape-+ ignores the current continuation, or “escapes from” the current continuation.

Answers: 11, 6

An escape procedure
Pretend that we have a procedure escape-+ that adds its arguments and returns this sum as the final answer, no matter what the context.
(* (escape‑+ 5 6) 3)  11
(escape-+ (escape-+ 2 4) 5)  6

We can say that escape-+ ignores the current continuation, or “escapes from” the current continuation.

Answers: 11, 6

Escaper (a mostly fictitious procedure)
More generally, suppose that we have a procedure escaper that takes any procedure as an argument and returns an equivalent escape procedure.
Thus (escaper +) creates a procedure that is equivalent to escape-+
(+ 3 ((escaper +) 4 5)) 
(+ ((escaper (lambda (x)
(- (* x 3) 7)))
4) 

Answers: 9, 8

Escaper (a mostly fictitious procedure)
More generally, suppose that we have a procedure escaper that takes a procedure as an argument and returns an equivalent escape procedure.
(escaper +) creates a procedure that is equivalent to escape-+
(+ 3 ((escaper +) 4 5))  9
(+ ((escaper (lambda (x)
(- (* x 3) 7)))
4)  8

Answers: 9, 8

You can define escaper in by loading escaper.ss
in the following way (from the command line):

escaper.ss is linked from the schedule page

sliderule 1:12pm > petite escaper.ss
Petite Version 6.7
Copyright (c) 1985-2001 Cadence Research Systems
> ((call/cc receiver-4))
“escaper is defined”
> (cdr ((escaper cdr) ‘(4 5 6)))
You can experiment with escaper

Escape Procedures
Let p be a procedure. If an application of p abandons the current continuation and does something else instead, we call p an escape procedure.
An example of a Scheme escape procedure that we have already used:
Is escaper an escape procedure?

Answer: error

“call-with” procedures
(call-with-values producer consumer)
The receiver is the consumer.
It receives the values returned by a call to the producer.
(call-with-output-file filename proc)
The receiver is proc.
It receives the output port obtained by opening the output file whose name is filename.
(call-with-current-continuation receiver)
The receiver receives the current continuation.

dining out example
from Springer and Friedman, Part 5 intro

(define dine-out
(lambda (restaurant)
(enter restaurant)
(read-menu)
(let ([food-I-ordered
(order-some-food)])
(eat food-I-ordered)
(pay-for food-I-ordered restaurant)
(exit restaurant))))
I will read an excerpt from the book
For future reference:
A photograph corresponds to a continuation.
“Taking a photograph” corresponds to applying call/cc to a receiver.
The receiver receives the photograph (continuation).
Rubbing a photograph and escaping corresponds to applying a continuation to an argument.

Call/cc definition and exampleS

call/cc is an abbreviation for
call‑with‑current‑continuation .
call/cc is a procedure that takes one argument; the argument is a receiver.
this receiver is a procedure that takes one argument;
that argument (in this case) is a continuation.
A continuation is a procedure (that takes one argument);
that continuation embodies the context of the application of call/cc.
The continuation is an escape procedure.
The application (call/cc receiver) has the same effect
as (receiver continuation), where the continuation is
an escape procedure that embodies the execution context of the entire call/cc expression.

call/cc definition summary
(call/cc receiver)  (receiver current-continuation),

Hence the name:
call‑with‑current‑continuation.

Rephrasing it: What is that continuation?

If c (for context) is a procedure that represents the execution context of this application of call/cc, then the continuation is equivalent to (escaper c).
call/cc does not create the continuation. It “reifies” it.

call/cc example
(call/cc receiver)  (receiver continuation)

a) (+ 3 (call/cc (lambda (k) (* 2 (k 5)))))
The receiver is
The context is
The continuation is
Thus (+ 3 (call/cc (lambda (k) (* 2 (k 5))))) is equivalent to

More call/cc examples
b) (+ 3 (call/cc (lambda (k) (* 2 5))))

c) (+ 3 (call/cc (lambda (k) (k (* 2 5)))))

(call/cc receiver)  (receiver continuation)

a) (+ 3 (call/cc (lambda (k) (* 2 (k 5)))))

Next day questions (use RSG):
What is a receiver?
Is call/cc a procedure, or syntax?
IS call/cc an escape procedure?
What does call/cc expect as its argument?
What is call/cc an abbreviation for?
What does the receiver receive?

More call/cc examples

d) (define xxx #f)
(+ 5 (call/cc (lambda (k)
(set! xxx k)
2))) ; xxx is equivalent to?
(* 7 (xxx 4))

(call/cc receiver)  (receiver continuation)

Next day questions (use RSG):
What is a receiver?
Is call/cc a procedure, or syntax?
IS call/cc an escape procedure?
What does call/cc expect as its argument?
What is call/cc an abbreviation for?
What does the receiver receive?

More call/cc examples

d) (define xxx #f)
(+ 5 (call/cc (lambda (k) take the photograph
(set! xxx k) save the photograph
2))) ; xxx is equivalent to?
(* 7 (xxx 4)) rub the photograph

(call/cc receiver)  (receiver continuation)

A simple call/cc example

(call/cc receiver)  (receiver continuation)

e) (call/cc procedure?)

call/cc in other languages
https://en.wikipedia.org/wiki/Call-with-current-continuation#Languages_implementing_call/cc
What you will find there:

f) List-index
Standard approach:
(define (list-index item L)
[(null? L) -1]
[(eq? (car L) item) 0]
[else (+ 1 (list-index item
(cdr L)))]))

What is the problem with this?
One solution: accumulator approach
But “standard recursion” seems so much more natural!
Can we use call/cc to escape with the -1 answer?

f) (define list-index
(lambda (sym L)
(lambda (answer)
(let loop ([L L])
(cond [(null? L) (answer -1)]
[(eqv? sym (car L)) 0]
[else (+ 1
(loop (cdr L)))]))))))
> (list-index ‘a ‘(b a c))
> (list-index ‘a ‘(b d c))

(call/cc receiver)  (receiver continuation)
g) ((car (call/cc list))
(list cdr 1 2 3))

Interlude: quotes
Premature optimization is the root of all evil in programming. – C.A.R. Hoare
Do you know what he is famous for?

There is no code so big, twisted, or complex that maintenance can’t make it worse. –

Computer Science is the only discipline in which we view adding a new wing to a building as being maintenance. –

All this from that short code?
h) (let ([f #f] [i 0])
(call/cc (lambda (k) (set! f k)))
(printf “~a~n” i)
(set! i (+ i 1))
(if (< i 10) (f "ignore"))) (call/cc receiver)  (receiver continuation) Strange indeed! i) (define strange1 (lambda (x) (display 1) (call/cc x) (display 2))) (lambda (k) k))) Error Handling with Continuations potentially erroring code ordinary code that relies on success } catch (errorflavor) { error handling code // try causes a call-cc, with a continuation that will bring us directly to the catch //post try code looks at the result to determine if an error happened, if so it invokes the catch, otherwise it returns the value Continuations with user input We often want functions that look like this (define (calc-complex-thing x y) (let ((user-val (ask-user-question)) (do-calculculation x y user-value))) But the reality is that interacting with the user actually forces us out of our functions. So we need ugly callback. (open-dialog “user question” (lambda (user-val) (do-calculation x y user-val))) ;; see how this function weirdly returns “mondo bizarro” example (define strange2 (lambda (x) (display 1) (call/cc x) (display 2) (call/cc x) (display 3))) (strange2 (call/cc (lambda (k) k))) We may not do this one in class; good practice for you. 程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com