1 / 22

# Advanced Scheme - PowerPoint PPT Presentation

Advanced Scheme. Continuations. Continuations. continuations allow you to save a computation at any place in its execution. In scheme, use the built-in function: call-with-current-continuation Can abbreviate as call/cc in most versions of scheme (including Dr Scheme)

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

Continuations

Continuations
• continuations allow you to save a computation at any place in its execution.
• In scheme, use the built-in function: call-with-current-continuation
• Can abbreviate as call/cc in most versions of scheme (including Dr Scheme)
• Can think of a continuation as a bookmark into a computation
call/cc
• Call/cc is a built-in function
• Takes as an argument a procedure of one parameter
• Call/cc calls the passed function and binds the continuation to the parameter of the function.
• When the parameter of the procedure is used in its body, computation jumps to the continuation and passes the argument to that point of the continuation
example
• In this example, call/cc is called after the + 1 computation is done
• The continuation at this point is bound to k and passed to the lambda
• k is used in the call (k 3)
• At this point the continuation is executed, ie execution is restarted right after the (+ 1 and the argument of k (ie 3) is passed as the result of the continuation.
• In other words it ignores any computation that occurred after the continuation started, but before the continuation was applied.

(+ 1 (call/cc

(lambda (k)

(+ 2 (k 3)))))

4

>

example

The continuation captures the computation. In this case it occurs right after the + 1, so when the continuation is used it will return its value to the +1 computation.

(+ 1 (call/cc

(lambda (k)

(+ 2 (k 3)))))

4

>

When the parameter is used ("called") it continues execution, returning to the execution it's parameter (3 in this case)

This function is immediately called. It is passed the "continuation"

example

(+ 1 (call/cc

(lambda (k)

(+ 2 (k 3)))))

4

>

Example 2
• In this example, call/cc is called after the + 1 computation is done, but there is more computation (ie values) after the call/cc function
• The continuation at the call/cc is bound to k and passed to the lambda
• k is used in the call (k 3)
• At this point the continuation is executed, ie execution is restarted right after the (+ 1 and the argument of k (ie 3) is passed as the result of the continuation.
• But there is more computation to be done after the call/cc, so the 4 and 10 are added to the result also!

(+ 1 (call/cc

(lambda (k)

(+ 2 (k 3)))) 4 10)

18

>

Example 2

The continuation captures the computation in the middle. In this case it occurs right after the + 1, but before the adding of 4 and 10.

(+ 1 (call/cc

(lambda (k)

(+ 2 (k 3)))) 4 10)

18

>

When k (the continuation) is called, we pick up at the + 1, pass in the argument of k (I.e., 3) and then finish the computation (add 4 and 10)

Escaping Continuations
• Continuations can be used to escape from computations
• Can conceptualize as “jumping” out of a procedure
Escaping Continuations: example

(define list-product

(lambda (s)

(letrec

((multList

(lambda (s)

(if (null? s)

1

(* (car s) (multList(cdr s)))

))))

(multList s))

)

)

• Works, but inefficient
• What if have a long list and end item is 0?
• Will return through the entire list and multiply each item by 0!
Escaping Continuations: example
• One solution: tail recursion
• Another solution: continuation

(define list-product

(lambda (s)

(call/cc

(lambda (exit)

(letrec

((multList

(lambda (s)

(if (null? s)

1

(if (= (car s) 0) (exit 0)

(* (car s) (multList(cdr s)))

)))))

(multList s))

))

))

Escaping Continuations: example 2
• Find an element in a list
• Use a built-in function for-each
• return does not exist in scheme
• (and yes, I know that we could use a recursive function instead)

(define find-item

(lambda (wanted? theList)

(for-each

(lambda (element)

(if (wanted? element)

(return element)))

theList)

#f))

To call:

(find-item (lambda (x) (equal? x 'a)) '(b c d a e f g))

This code won’t run! The function return doesn’t exist!

How can we return?

Escaping Continuations: example 2
• Instead of return use a continuation

(define find-item

(lambda (wanted? theList)

(call/cc

(lambda (return)

(for-each

(lambda (element)

(if (wanted? element)

(return #t)))

theList)

#f))))

The return becomes a continuation

Escaping Continuations: example 3deep recursion

; adds a number to the product of a list of numbers

(define product+

(lambda (n nums)

(lambda (exit-on-zero)

(letrec

((product

(lambda (nums)

(cond

((null? nums) 1)

((number? (car nums))

(cond

((zero? (car nums))(exit-on-zero 0))

(else (* (car nums)

(product (cdr nums))))))

(else (* (product (car nums))

(product (cdr nums))))))))

(+ n (product nums))))))

The exit-on-zero becomes a continuation

Saving Continuations
• Can save a continuation and use it later

(define r #f)

(+ 1 (call/cc

(lambda (k)

(set! r k)

(k 3))))

4

> (r 1)

2

> (r 10)

11

> (r 32)

33

> (+ 3 4 (r 20))

21

>

Background: writeln

;; first must define writeln

(define writeln

(lambda lst

;; need a helper function to deal with the lst; a recursive call to writeln

;; will place lst into another list

(letrec ((helper

(lambda (newlst)

(if (not (null? newlst))

(begin

(display (car newlst))

(display #\space)

(helper (cdr newlst)))

(newline)))))

(helper lst))))

Looping with Continuations

; loops with continuations

(define countdown

(lambda (n)

(writeln "This only appears once")

(let ((pair (message "Exit" (attempt (message "Enter" n)))))

(let ((v (car pair))

(writeln " The non-negative-number: " v)

(if (positive? v)

(returner (list (sub1 v) returner))

(writeln "Blastoff!"))))))

(define message

(lambda (direction value)

(writeln " " direction "ing attempt with value: " value)

value))

(define attempt

(lambda (n)

(let ((receiver (lambda (proc)(list n proc))))

• Welcome to DrScheme, version 209.
• Language: Graphical (MrEd, includes MzScheme).
• (countdown 10)
• This only appears once
• Enter ing attempt with value: 10
• Exit ing attempt with value: (10 #<continuation>)
• The non-negative-number: 10
• Exit ing attempt with value: (9 #<continuation>)
• The non-negative-number: 9
• Exit ing attempt with value: (8 #<continuation>)
• The non-negative-number: 8
• Exit ing attempt with value: (7 #<continuation>)
• The non-negative-number: 7
• Exit ing attempt with value: (6 #<continuation>)
• The non-negative-number: 6
• Exit ing attempt with value: (5 #<continuation>)
• The non-negative-number: 5
• Exit ing attempt with value: (4 #<continuation>)
• The non-negative-number: 4
• Exit ing attempt with value: (3 #<continuation>)
• The non-negative-number: 3
• Exit ing attempt with value: (2 #<continuation>)
• The non-negative-number: 2
• Exit ing attempt with value: (1 #<continuation>)
• The non-negative-number: 1
• Exit ing attempt with value: (0 #<continuation>)
• The non-negative-number: 0
• Blastoff!
Named let expressions
• Background: a named let:

(define test

(lambda ()

(letrec ((countdown (lambda (i)

(if (= i 0) 'liftoff

(begin

(display i)

(newline)

(countdown (- i 1)))))))

(countdown 10))))

(define test

(lambda ()

(letrec ((countdown (lambda (i)

(if (= i 0) 'liftoff

(begin

(display i)

(newline)

(countdown (- i 1))))

)))

(countdown 10))

))

First statement in body of countdown

First statement in body of countdown

Second statement in body of countdown

Second statement in body of countdown

Named let expressions
• This is an infinite loop:

(define test

(lambda ()

(letrec ((countdown (lambda (i)

(if (= i 0) 'liftoff

(begin

(display i)

(newline)

(countdown (- i 1))))

(countdown 20))))

(countdown 10))

))

(define test

(lambda ()

(let countdown ((i 10))

(if (= i 0) 'liftoff

(begin

(display i)

(newline)

(countdown (- i 1))))

(countdown 20)

)))

The second statement produces an infinite loop

Coroutines

(define hefty-computation

(lambda (do-other-stuff)

(letrec ((junk

(lambda (n)

(display "Hefty computation (a). ")

(display n)

(newline)

(set! do-other-stuff (call/cc do-other-stuff))

(display "Hefty computation (b). ")

(display n)

(newline)

(set! do-other-stuff (call/cc do-other-stuff))

(display "Hefty computation (c). ")

(display n)

(newline)

(set! do-other-stuff (call/cc do-other-stuff))

(if (> n 0)

(junk (- n 1)))))

)

(junk 5))))

Coroutines

;; notationally displays a clock

;; uses a named let

(define superfluous-computation

(lambda (do-other-stuff)

(let loop()

(for-each (lambda (graphic)

(display graphic)

(newline)

(set! do-other-stuff (call/cc do-other-stuff)))

'("Straight-up" "Quarter after" "Half past" "Quarter till"))

(loop))))

(hefty-computation superfluous-computation)

Coroutines

;; notationally displays a clock

;; uses a letrec

(define superfluous-computation

(lambda (do-other-stuff)

(letrec

((loop

(lambda ()

(for-each (lambda (graphic)

(display graphic)

(newline)

(set! do-other-stuff (call/cc do-other-stuff)))

'("Straight-up" "Quarter after" "Half past" "Quarter till"))

(loop) ;; this causes infinite recursion in the local function

)))

(loop) ;; the single statement in the letrec

)))

(hefty-computation superfluous-computation)