Continuations in Scheme

Slides:



Advertisements
Similar presentations
Adapted from Scott, Chapter 6:: Control Flow Programming Language Pragmatics Michael L. Scott.
Advertisements

Continuations in Scheme. Control in Scheme Why doesn’t Scheme have a return function? Maybe we don’t need it to indicate the normal function return spots.
Control Structures Any mechanism that departs from straight-line execution: –Selection: if-statements –Multiway-selection: case statements –Unbounded iteration:
Variables, Environments and Closures. Overview We will Touch on the notions of variable extent and scope Introduce the notions of lexical scope and.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Prof. Fateman CS164 Lecture 241 Other Control Flow ideas: Throw, Catch, Continuations and Call/CC Lecture 24.
Continuations COS 441 Princeton University Fall 2004.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
CSE S. Tanimoto Lambda Calculus 1 Lambda Calculus What is the simplest functional language that is still Turing complete? Where do functional languages.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Streams and Lazy Evaluation in Lisp and Scheme. Overview Examples of using closures Delay and force Macros Different models of expression evaluation –
Functional Programming in Scheme and Lisp.
Variables, Environments and Closures. Overview Touch on the notions of variable extent and scope Introduce the notions of lexical scope and dynamic.
Scheme Profs Tim Sheard and Andrew Black CS 311 Computational Structures.
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
1/33 Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
Control Structures CSC 358/ Outline Midterm Lab #3 Homework #4 Sequential structures Conditional structures Unconditional branching Iteration.
Functional Programming
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation
MSc/ICY Software Workshop , Semester 2
Expressions and Assignment
CS 326 Programming Languages, Concepts and Implementation
6.001 Jeopardy.
6.001 SICP Variations on a Scheme
6.001 SICP Compilation Context: special purpose vs. universal machines
Variables, Environments and Closures
Closures and Streams cs784(Prasad) L11Clos
COP4020 Programming Languages
Env. Model Implementation
Chapter 8: Control Structures
Imperative languages Most familiar: computation modifies store
Nondeterministic Evaluation
6.001 SICP Data abstractions
Control Flow.
Variables, Environments and Closures
CS1100 Computational Engineering
Lecture 18 Infinite Streams and
Structured Program
slides created by Marty Stepp
Dynamic Scoping Lazy Evaluation
Closure Closure binds a first-class function and a lexical environment together This is a complex topic, so we will build up our understanding of it we.
Continuations in Scheme
Background In his classic 1972 paper on definitional interpreters, John Reynolds introduced two key techniques: Continuation-passing style - Makes.
Abstraction and Repetition
Functional interface.
CSE S. Tanimoto Explicit Function Application
6.001 SICP Further Variations on a Scheme
Continuations in Scheme
Explicit Application of Procedures, and Explicit Evaluation
Functional Programming Concepts
Streams, Delayed Evaluation and a Normal Order Interpreter
Lisp, Then and Now.
Streams and Lazy Evaluation in Lisp and Scheme
Lisp: Using Functions as Data
Streams and Lazy Evaluation in Lisp and Scheme
6.001 SICP Variations on a Scheme
Functional Programming Concepts
Defining Functions with DEFUN
Abstraction and Repetition
The Recursive Descent Algorithm
Lisp: Using Functions as Data
Continuations in Scheme
CSE S. Tanimoto Lambda Calculus
Functional Programming Concepts
Introduction to the Lab
Streams and Lazy Evaluation in Lisp and Scheme
Exception Handling.
Programming Language  C Control Flow
Abstraction and Repetition
Presentation transcript:

Continuations in Scheme

Overview Control operators Concept of a continuation in a functional programming language Scheme’s call/cc

Control operators Control operators manipulate the order of program steps Examples: goto, if , loops, return, break, exit A pure functional programming language typically only has one of these: if Well, scheme does have do Users can define many of their own control operators with macros (e.g., via define-syntax) What about return?

Control in Scheme Why doesn’t Scheme have a return function? Maybe we don’t need it to indicate the normal function return spots (define (find-prime1 n) ;; returns the first prime ≥ n (if (prime? n) n (find-prime1 (add1 n)))) But how about places where we want to “break out” of a computation (define (find-prime2 n) ;; returns first prine between n and n**2 (for-each (lambda (x) (and (prime? x) (return x)) (integers n (* n n))))

Catch and Throw in Lisp Lisp introduced (in the 70’s) catch and throw to give a non-local return capability It was a very useful generalization of return (throw <expr>) causes a return from the nearest matching (catch <x>) found on stack (defun foo-outer () (catch (foo-inner))) (defun foo-inner () … (if x (throw t)) ...) Both take an optional tag argument; (throw ‘foo) can be caught by (catch ‘foo) or (catch)

Scheme’s functional approach Scheme provides some primitive built-ins that can create these and other control functions call-with-current-continuation is the main one typically also bound to call/cc call/cc provides a way to escape out of computation to someplace higher on the stack It’s used to create other powerful control mechanisms, like co-routines and backtracking call/cc does this in a decidedly functional way

Continuation A continuation represents the “future” of a computation at certain moment Consider the Scheme expression (* (f1 exp1) (f2 (f3 4) (f5 exp2))) The continuation of (f3 4) in that expression is the function (lambda (X) (* (f1 exp1) (f2 X (f5 exp2)))) The continuation c of an expression e is a function that awaits the value of e and proceeds with the computation

Call/cc call/css takes a unary function f as its only argument When called, it reifies the current continuation as an object and applies f to it

example > (for-each (lambda (x) ( + x x)) '(1 2 3)) > (for-each (lambda (x) (printf "~s " x)) '(1 2 3)) > 1 2 3 > > (call/cc (lambda (exit) (for-each (lambda (x) (if (negative? x) (exit x) #f)) '(54 0 37 -3 245 19)) #t)) -3

Implementing return (define (search pred? lst) ; returns first item in LST satisfying pred? or #f (call/cc (lambda (return) (for-each (lambda (item) (if (pred? item) (return item) #f)) lst) #f)))

The return can be non-local (define (treat item like-it) ; Call like-it with a custom argument when we like item (if (good-item? item) (like-it 'fnord) #f)) (define good-item? odd?) (define (search2 treat lst) ; Call treat with every item in lst and a procedure to call ; when treat likes this item. (call/cc (lambda (return) (for-each (lambda (item) (treat item return)) lst) #f)))

We can re-call continuations > (define return #f) > (+ 1 (call/cc (lambda (cont) (set! return cont) 2)) 3) 6 > return #<continuation> > (return 100) 104 cont is bound to a continuation (i.e., unary function) that takes a value x and computes (+ 1 x 3)

re-call continuations 2 > (define a 1) (define b 2) (define c 3) (define return #f) > (define (add-abc) (+ a (call/cc (lambda (cont) (set! return cont) b)) c)) > (add-abc) 6 > return #<continuation> > (return 100) 104 > (set! a 1000) > (return 100) 104 (set! c 999) 1100

Coroutines Coroutines are procedures that persist after they exit and then can be re-entered They maintain their state in between calls They provide an alternative mechanism to threads for interleaving two processes You can implement coroutines in Scheme with continuations

Hefty and Superfluous (define (hefty other) (let loop ((n 5)) (printf "Hefty: ~s\n" n) (set! do-other (call/cc other)) (printf "Hefty (b)\n") (printf "Hefty (c)\n") (if (> n 0) (loop (- n 1)) #f))) (define clock-positions '("Straight up.” "Quarter after." "Half past.” "Quarter til.")) (define (superfluous other) (let loop () (for-each (lambda (graphic) (printf "~s\n" graphic) (set! other (call/cc other))) clock-positions (loop)))

Hefty and Superfluous > (hefty superfluous) Hefty: 5 "Straight up." Hefty (b) "Quarter after." Hefty (c) "Half past." Hefty: 4 "Quarter til.” … … Hefty (c) "Half past." Hefty: 0 "Quarter til." Hefty (b) "Straight up." "Quarter after." #f

Summary Continuations are a both weird and hard to understand They’re also expensive to implement and use Most languages choose to add those control features (e.g., return, catch throw) that programmers understand and want These are also added in Scheme via libraries But Scheme is mostly a PL for experimenting with PLs and new PL ideas and features