Control

513 views

Published on

Published in: Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
513
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Control

  1. 1. Control in Sequential Languages + some discussion of functional programming John Mitchell CS 242 Reading: Chapter 8, Sections 8.1 – 8.3 (only) Chapter 4, Section 4.4 (only) Fall 2008
  2. 2. JavaScript blocks and scopes <ul><li>{ } groups JavaScript statements </li></ul><ul><ul><li>Does not provide a separate scope </li></ul></ul><ul><li>Blocks w/scope can be expressed using function </li></ul><ul><ul><li>(function(){ … })() - create function of no args and call </li></ul></ul><ul><ul><li>Example </li></ul></ul><ul><ul><li>var y=0; </li></ul></ul><ul><ul><li>(function () { // begin block </li></ul></ul><ul><ul><li>var x=2; // local variable x </li></ul></ul><ul><ul><li>y = y+x; </li></ul></ul><ul><ul><li>}) (); // end block </li></ul></ul>RECAP
  3. 3. Homework 1, Problem 6 <ul><ul><li>var x = 5; </li></ul></ul><ul><ul><li>function f(y) {return (x+y)-2}; </li></ul></ul><ul><ul><li>function g(h){var x = 7; return h(x)}; </li></ul></ul><ul><ul><li>{var x = 10; g(f)}; </li></ul></ul><ul><ul><li>var x = 5; </li></ul></ul><ul><ul><li>function f(y) {return (x+y)-2}; </li></ul></ul><ul><ul><li>function g(h){var x = 7; return h(x)}; </li></ul></ul><ul><ul><li>{var x = 10; g(f)}; </li></ul></ul><ul><ul><li>(function (){ </li></ul></ul><ul><ul><li>var x = 5; </li></ul></ul><ul><ul><li>(function (){ </li></ul></ul><ul><ul><li>function f(y) {return (x+y)-2}; </li></ul></ul><ul><ul><li>(function (){ </li></ul></ul><ul><ul><li>function g(h){var x = 7; return h(x)}; </li></ul></ul><ul><ul><li>(function (){ </li></ul></ul><ul><ul><li>var x = 10; g(f); </li></ul></ul><ul><ul><li>})() </li></ul></ul><ul><ul><li>})() </li></ul></ul><ul><ul><li>})() </li></ul></ul><ul><ul><li>})() </li></ul></ul>
  4. 4. Topics <ul><li>Structured Programming </li></ul><ul><ul><li>Go to considered harmful </li></ul></ul><ul><li>Exceptions </li></ul><ul><ul><li>“ structured” jumps that may return a value </li></ul></ul><ul><ul><li>dynamic scoping of exception handler </li></ul></ul><ul><li>Continuations </li></ul><ul><ul><li>Function representing the rest of the program </li></ul></ul><ul><ul><li>Generalized form of tail recursion </li></ul></ul><ul><li>Discussion of functional programming </li></ul><ul><ul><li>Relevant to Haskell, section 4.4 of text </li></ul></ul>
  5. 5. Fortran Control Structure <ul><ul><li>10 IF (X .GT. 0.000001) GO TO 20 </li></ul></ul><ul><ul><li>11 X = -X </li></ul></ul><ul><ul><li>IF (X .LT. 0.000001) GO TO 50 </li></ul></ul><ul><ul><li>20 IF (X*Y .LT. 0.00001) GO TO 30 </li></ul></ul><ul><ul><li>X = X-Y-Y </li></ul></ul><ul><ul><li>30 X = X+Y </li></ul></ul><ul><ul><li>... </li></ul></ul><ul><ul><li>50 CONTINUE </li></ul></ul><ul><ul><li>X = A </li></ul></ul><ul><ul><li>Y = B-A </li></ul></ul><ul><ul><li>GO TO 11 </li></ul></ul><ul><ul><li>… </li></ul></ul>Similar structure may occur in assembly code
  6. 6. Historical Debate <ul><li>Dijkstra, Go To Statement Considered Harmful </li></ul><ul><ul><li>Letter to Editor, C ACM , March 1968 </li></ul></ul><ul><ul><li>Link on CS242 web site </li></ul></ul><ul><li>Knuth, Structured Prog. with go to Statements </li></ul><ul><ul><li>You can use goto, but do so in structured way … </li></ul></ul><ul><li>Continued discussion </li></ul><ul><ul><li>Welch, “GOTO (Considered Harmful) n , n is Odd” </li></ul></ul><ul><li>General questions </li></ul><ul><ul><li>Do syntactic rules force good programming style? </li></ul></ul><ul><ul><li>Can they help? </li></ul></ul>
  7. 7. Advance in Computer Science <ul><li>Standard constructs that structure jumps </li></ul><ul><ul><li>if … then … else … end </li></ul></ul><ul><ul><li>while … do … end </li></ul></ul><ul><ul><li>for … { … } </li></ul></ul><ul><ul><li>case … </li></ul></ul><ul><li>Modern style </li></ul><ul><ul><li>Group code in logical blocks </li></ul></ul><ul><ul><li>Avoid explicit jumps except for function return </li></ul></ul><ul><ul><li>Cannot jump into middle of block or function body </li></ul></ul>
  8. 8. Exceptions: Structured Exit <ul><li>Terminate part of computation </li></ul><ul><ul><li>Jump out of construct </li></ul></ul><ul><ul><li>Pass data as part of jump </li></ul></ul><ul><ul><li>Return to most recent site set up to handle exception </li></ul></ul><ul><ul><li>Unnecessary activation records may be deallocated </li></ul></ul><ul><ul><ul><li>May need to free heap space, other resources </li></ul></ul></ul><ul><li>Two main language constructs </li></ul><ul><ul><li>Declaration to establish exception handler </li></ul></ul><ul><ul><li>Statement or expression to raise or throw exception </li></ul></ul>Often used for unusual or exceptional condition; other uses too
  9. 9. JavaScript Exceptions <ul><ul><li>throw e //jump to catch, passing exception object as parameter </li></ul></ul><ul><ul><li>try { … //code to try </li></ul></ul><ul><ul><li>} catch (e if e == …) { … //catch if first condition true </li></ul></ul><ul><ul><li>} catch (e if e == …) { … //catch if second condition true </li></ul></ul><ul><ul><li>} catch (e if e == …) { … //catch if third condition true </li></ul></ul><ul><ul><li>} catch (e){ … // catch any exception </li></ul></ul><ul><ul><li>} finally { … //code to execute after everything else </li></ul></ul><ul><ul><li>} </li></ul></ul>http://developer.mozilla.org/En/Core_JavaScript_1.5_Guide/ Exception_Handling_Statements
  10. 10. JavaScript Example <ul><ul><li>function invert(matrix) { </li></ul></ul><ul><ul><li>if … throw “Determinant”; </li></ul></ul><ul><ul><li>… </li></ul></ul><ul><ul><li>}; </li></ul></ul><ul><ul><li>try { … invert(myMatrix); … </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>catch (e) { … </li></ul></ul><ul><ul><li>// recover from error </li></ul></ul><ul><ul><li>} </li></ul></ul>
  11. 11. ML Example (book discusses ML) <ul><ul><li>exception Determinant; (* declare exception name *) </li></ul></ul><ul><ul><li>fun invert (M) = (* function to invert matrix *) </li></ul></ul><ul><ul><li>… </li></ul></ul><ul><ul><li>if … </li></ul></ul><ul><ul><li>then raise Determinant (* exit if Det=0 *) </li></ul></ul><ul><ul><li>else … </li></ul></ul><ul><ul><li>end; </li></ul></ul><ul><ul><li>... </li></ul></ul><ul><ul><li>invert (myMatrix) handle Determinant => … ; </li></ul></ul>Value for expression if determinant of myMatrix is 0 try catch
  12. 12. C++ Example <ul><ul><li>Matrix invert(Matrix m) { </li></ul></ul><ul><ul><li>if … throw Determinant; </li></ul></ul><ul><ul><li>… </li></ul></ul><ul><ul><li>}; </li></ul></ul><ul><ul><li>try { … invert(myMatrix); … </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>catch (Determinant) { … </li></ul></ul><ul><ul><li>// recover from error </li></ul></ul><ul><ul><li>} </li></ul></ul>
  13. 13. ML Exceptions (cover briefly so book is useful to you) <ul><li>Declaration </li></ul><ul><ul><li>exception  name  of  type  </li></ul></ul><ul><ul><ul><li>gives name of exception and type of data passed when raised </li></ul></ul></ul><ul><li>Raise </li></ul><ul><ul><li>raise  name   parameters  </li></ul></ul><ul><ul><ul><li>expression form to raise and exception and pass data </li></ul></ul></ul><ul><li>Handler </li></ul><ul><ul><li> exp1  handle  pattern  =>  exp2  </li></ul></ul><ul><ul><ul><li>evaluate first expression </li></ul></ul></ul><ul><ul><ul><li>if exception that matches pattern is raised, </li></ul></ul></ul><ul><ul><ul><li>then evaluate second expression instead </li></ul></ul></ul><ul><ul><ul><li>General form allows multiple patterns. </li></ul></ul></ul>
  14. 14. C++ vs ML Exceptions <ul><li>C++ exceptions </li></ul><ul><ul><li>Can throw any type </li></ul></ul><ul><ul><li>Stroustrup: “I prefer to define types with no other purpose than exception handling. This minimizes confusion about their purpose. In particular, I never use a built-in type, such as int, as an exception.” -- The C++ Programming Language, 3 rd ed. </li></ul></ul><ul><li>ML exceptions </li></ul><ul><ul><li>Exceptions are a different kind of entity than types. </li></ul></ul><ul><ul><li>Declare exceptions before use </li></ul></ul><ul><ul><li>Similar, but ML requires the recommended C++ style. </li></ul></ul>
  15. 15. Which handler is used? <ul><li>Dynamic scoping of handlers </li></ul><ul><ul><li>First call handles exception one way </li></ul></ul><ul><ul><li>Second call handles exception another </li></ul></ul><ul><ul><li>General dynamic scoping rule </li></ul></ul><ul><ul><ul><li>Jump to most recently established handler on run-time stack </li></ul></ul></ul><ul><li>Dynamic scoping is not an accident </li></ul><ul><ul><li>User knows how to handler error </li></ul></ul><ul><ul><li>Author of library function does not </li></ul></ul><ul><ul><ul><li>exception Ovflw; </li></ul></ul></ul><ul><ul><ul><li>fun reciprocal(x) = </li></ul></ul></ul><ul><ul><ul><li>if x<min then raise Ovflw else 1/x; </li></ul></ul></ul><ul><ul><ul><li>(reciprocal(x) handle Ovflw=>0) / (reciprocal(y) handle Ovflw=>1); </li></ul></ul></ul>try try catch catch throw
  16. 16. Exception for Error Condition <ul><ul><li>- datatype ‘a tree = LF of ‘a | ND of (‘a tree)*(‘a tree) </li></ul></ul><ul><ul><li>- exception No_Subtree; </li></ul></ul><ul><ul><li>- fun lsub (LF x) = raise No_Subtree </li></ul></ul><ul><ul><li>| lsub (ND(x,y)) = x; </li></ul></ul><ul><ul><li>> val lsub = fn : ‘a tree -> ‘a tree </li></ul></ul><ul><ul><li>This function raises an exception when there is no reasonable value to return </li></ul></ul><ul><ul><li>We’ll look at typing later. </li></ul></ul>
  17. 17. Exception for Efficiency <ul><li>Function to multiply values of tree leaves </li></ul><ul><ul><li>fun prod(LF x) = x </li></ul></ul><ul><ul><li>| prod(ND(x,y)) = prod(x) * prod(y); </li></ul></ul><ul><li>Optimize using exception </li></ul><ul><ul><li>fun prod(tree) = </li></ul></ul><ul><ul><li>let exception Zero </li></ul></ul><ul><ul><li>fun p(LF x) = if x=0 then (raise Zero) else x </li></ul></ul><ul><ul><li>| p(ND(x,y)) = p(x) * p(y) </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>p(tree) handle Zero=>0 </li></ul></ul><ul><ul><li>end; </li></ul></ul>
  18. 18. Dynamic Scope of Handler <ul><ul><li>exception X; </li></ul></ul><ul><ul><li>(let fun f(y) = raise X </li></ul></ul><ul><ul><li>and g(h) = h(1) handle X => 2 </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>g(f) handle X => 4 </li></ul></ul><ul><ul><li>end) handle X => 6; </li></ul></ul>Which handler is used? See JavaScript next slide scope handler
  19. 19. Dynamic Scope of Handler <ul><ul><li>try{ </li></ul></ul><ul><ul><li>function f(y) { throw “exn”}; </li></ul></ul><ul><ul><li>function g(h){ try {h(1)} catch(e){return 2} }; </li></ul></ul><ul><ul><li>try { </li></ul></ul><ul><ul><li>g(f) </li></ul></ul><ul><ul><li>} catch(e){4}; </li></ul></ul><ul><ul><li>} catch(e){6}; </li></ul></ul>Which catch catches the throw?
  20. 20. Dynamic Scope of Handler <ul><ul><li>try{ </li></ul></ul><ul><ul><li>function f(y) { throw “exn”}; </li></ul></ul><ul><ul><li>function g(h){ try {h(1)} </li></ul></ul><ul><ul><li>catch(e){return 2} </li></ul></ul><ul><ul><li>}; </li></ul></ul><ul><ul><li>try { </li></ul></ul><ul><ul><li>g(f) </li></ul></ul><ul><ul><li>} catch(e){4}; </li></ul></ul><ul><ul><li>} catch(e){6}; </li></ul></ul>g(f) f(1) Dynamic scope: find first handler, going up the dynamic call chain JavaScript version catch(e) 6 formal h catch(e) 2 access link formal y 1 access link fun f access link access link fun g catch(e) 4 access link
  21. 21. Dynamic Scope of Handler <ul><ul><li>exception X; </li></ul></ul><ul><ul><li>(let fun f(y) = raise X </li></ul></ul><ul><ul><li>and g(h) = h(1) handle X => 2 </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>g(f) handle X => 4 </li></ul></ul><ul><ul><li>end) handle X => 6; </li></ul></ul>g(f) f(1) Dynamic scope: find first X handler, going up the dynamic call chain leading to raise X. Book version (ML) handler X 6 formal h handler X 2 access link formal y 1 access link fun f access link access link fun g handler X 4 access link
  22. 22. Compare to static scope of variables <ul><ul><li>exception X; </li></ul></ul><ul><ul><li>(let fun f(y) = raise X </li></ul></ul><ul><ul><li>and g(h) = h(1) </li></ul></ul><ul><ul><li>handle X => 2 </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>g(f) handle X => 4 </li></ul></ul><ul><ul><li>end) handle X => 6; </li></ul></ul><ul><ul><li>val x=6; </li></ul></ul><ul><ul><li>(let fun f(y) = x </li></ul></ul><ul><ul><li>and g(h) = let val x=2 in </li></ul></ul><ul><ul><li>h(1) </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>let val x=4 in g(f) </li></ul></ul><ul><ul><li>end); </li></ul></ul>Book version (ML)
  23. 23. Compare to static scope of variables <ul><ul><li>try{ </li></ul></ul><ul><ul><li>function f(y) { throw “exn”}; </li></ul></ul><ul><ul><li>function g(h){ try {h(1)} </li></ul></ul><ul><ul><li>catch(e){return 2} </li></ul></ul><ul><ul><li>}; </li></ul></ul><ul><ul><li>try { </li></ul></ul><ul><ul><li>g(f) </li></ul></ul><ul><ul><li>} catch(e){4}; </li></ul></ul><ul><ul><li>} catch(e){6}; </li></ul></ul><ul><ul><li>var x=6; </li></ul></ul><ul><ul><li>function f(y) { return x}; </li></ul></ul><ul><ul><li>function g(h){ var x=2; </li></ul></ul><ul><ul><li>return h(1) </li></ul></ul><ul><ul><li>}; </li></ul></ul><ul><ul><li>(function (y) { </li></ul></ul><ul><ul><li>var x=4; </li></ul></ul><ul><ul><li>g(f) </li></ul></ul><ul><ul><li>})(0); </li></ul></ul>JavaScript version declaration declaration
  24. 24. Static Scope of Declarations <ul><ul><li>var x=6; </li></ul></ul><ul><ul><li>function f(y) { return x}; </li></ul></ul><ul><ul><li>function g(h){ </li></ul></ul><ul><ul><li>var x=2; return h(1) }; </li></ul></ul><ul><ul><li>(function (y) { </li></ul></ul><ul><ul><li>var x=4; g(f) </li></ul></ul><ul><ul><li>})(0); </li></ul></ul>g(f) f(1) Static scope: find first x, following access links from the reference to X. JavaScript version var x 6 formal h var x 2 access link formal y 1 access link function f access link access link function g var x 4 access link
  25. 25. Static Scope of Declarations <ul><ul><li>val x=6; </li></ul></ul><ul><ul><li>(let fun f(y) = x </li></ul></ul><ul><ul><li>and g(h) = let val x=2 in </li></ul></ul><ul><ul><li>h(1) </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>let val x=4 in g(f) </li></ul></ul><ul><ul><li>end); </li></ul></ul>g(f) f(1) Static scope: find first x, following access links from the reference to X. Book version (ML) val x 6 formal h val x 2 access link formal y 1 access link fun f access link access link fun g val x 4 access link
  26. 26. Typing of Exceptions <ul><li>Typing of raise  exn  </li></ul><ul><ul><li>Recall definition of typing </li></ul></ul><ul><ul><ul><li>Expression e has type t if normal termination of e </li></ul></ul></ul><ul><ul><ul><li>produces value of type t </li></ul></ul></ul><ul><ul><li>Raising exception is not normal termination </li></ul></ul><ul><ul><ul><li>Example: 1 + raise X </li></ul></ul></ul><ul><li>Typing of handle  exn  =>  value  </li></ul><ul><ul><li>Converts exception to normal termination </li></ul></ul><ul><ul><li>Need type agreement </li></ul></ul><ul><ul><li>Examples </li></ul></ul><ul><ul><ul><li>1 + ((raise X) handle X => e) Type of e must be int </li></ul></ul></ul><ul><ul><ul><li>1 + (e 1 handle X => e 2 ) Type of e 1, e 2 must be int </li></ul></ul></ul>
  27. 27. Exceptions and Resource Allocation <ul><ul><li>exception X; </li></ul></ul><ul><ul><li>(let </li></ul></ul><ul><ul><li>val x = ref [1,2,3] </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>let </li></ul></ul><ul><ul><li>val y = ref [4,5,6] </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>… raise X </li></ul></ul><ul><ul><li>end </li></ul></ul><ul><ul><li>end); handle X => ... </li></ul></ul><ul><li>Resources may be allocated between handler and raise </li></ul><ul><li>May be “garbage” after exception </li></ul><ul><li>Examples </li></ul><ul><ul><li>Memory </li></ul></ul><ul><ul><li>Lock on database </li></ul></ul><ul><ul><li>Threads </li></ul></ul><ul><ul><li>… </li></ul></ul>General problem: no obvious solution
  28. 28. Continuations <ul><li>Idea: </li></ul><ul><ul><li>The continuation of an expression is “the remaining work to be done after evaluating the expression” </li></ul></ul><ul><ul><li>Continuation of e is a function normally applied to e </li></ul></ul><ul><li>General programming technique </li></ul><ul><ul><li>Capture the continuation at some point in a program </li></ul></ul><ul><ul><li>Use it later: “jump” or “exit” by function call </li></ul></ul><ul><li>Useful in </li></ul><ul><ul><li>Compiler optimization: make control flow explicit </li></ul></ul><ul><ul><li>Operating system scheduling, multiprogramming </li></ul></ul><ul><ul><li>Web site design, other applications </li></ul></ul>
  29. 29. Example of Continuation Concept <ul><li>Expression </li></ul><ul><ul><li>2*x + 3*y + 1/x + 2/y </li></ul></ul><ul><li>What is continuation of 1/x? </li></ul><ul><ul><li>Remaining computation after division </li></ul></ul><ul><ul><li>var before = 2*x + 3*y; </li></ul></ul><ul><ul><li>function cont(d) {return (before + d + 2/y)}; </li></ul></ul><ul><ul><li>cont (1/x); </li></ul></ul>JavaScript version
  30. 30. Example of Continuation Concept <ul><li>Expression </li></ul><ul><ul><li>2*x + 3*y + 1/x + 2/y </li></ul></ul><ul><li>What is continuation of 1/x? </li></ul><ul><ul><li>Remaining computation after division </li></ul></ul><ul><ul><li>let val before = 2*x + 3*y </li></ul></ul><ul><ul><li>fun continue(d) = before + d + 2/y </li></ul></ul><ul><ul><li>in </li></ul></ul><ul><ul><li>continue (1/x) </li></ul></ul><ul><ul><li>end </li></ul></ul>Book version (ML)
  31. 31. Example: Tail Recursive Factorial <ul><li>Standard recursive function </li></ul><ul><ul><li>fact(n) = if n=0 then 1 else n*fact(n-1) </li></ul></ul><ul><li>Tail recursive </li></ul><ul><ul><li>f(n,k) = if n=0 then k else f(n-1, n*k) </li></ul></ul><ul><ul><li>fact(n) = f(n,1) </li></ul></ul><ul><li>How could we derive this? </li></ul><ul><ul><li>Transform to continuation-passing form </li></ul></ul><ul><ul><li>Optimize continuation functions to single integer </li></ul></ul>
  32. 32. Continuation view of factorial <ul><ul><li>fact(n) = if n=0 then 1 else n*fact(n-1) </li></ul></ul><ul><ul><li>fact(9) </li></ul></ul><ul><ul><li>fact(8) </li></ul></ul><ul><ul><li>fact(7) </li></ul></ul><ul><ul><li>This invocation multiplies by 9 and returns </li></ul></ul><ul><ul><li>Continuation of fact(8) is  x. 9*x </li></ul></ul><ul><ul><li>Multiplies by 8 and returns </li></ul></ul><ul><ul><li>Continuation of fact(7) is </li></ul></ul><ul><ul><li> y. (  x. 9*x) (8*y) </li></ul></ul><ul><ul><li>Multiplies by 7 and returns </li></ul></ul><ul><ul><li>Continuation of fact(6) is </li></ul></ul><ul><ul><li> z. (  y. (  x. 9*x) (8*y)) (7*z) </li></ul></ul>return n 9 ... return n 8 ... return n 7 ...
  33. 33. Derivation of tail recursive form <ul><li>Standard function </li></ul><ul><ul><li>fact(n) = if n=0 then 1 else n*fact(n-1) </li></ul></ul><ul><li>Continuation form </li></ul><ul><ul><li>fact(n, k) = if n=0 then k(1) </li></ul></ul><ul><ul><li>else fact(n-1,  x.k ( n*x) ) </li></ul></ul><ul><ul><li>fact(n,  x.x) computes n! </li></ul></ul><ul><li>Example computation </li></ul><ul><ul><li>fact(3,  x.x) = fact(2,  y. ( (  x.x) ( 3*y) ) ) </li></ul></ul><ul><ul><li>= fact(1,  x. ( (  y.3*y)(2*x) ) ) </li></ul></ul><ul><ul><li>=  x. ( (  y.3*y)(2*x) ) 1 = 6 </li></ul></ul>continuation
  34. 34. Tail Recursive Form <ul><li>Optimization of continuations </li></ul><ul><ul><li>fact(n,a) = if n=0 then a </li></ul></ul><ul><ul><li>else fact(n-1, n*a ) </li></ul></ul><ul><ul><li>Each continuation is effectively  x.(a*x) for some a </li></ul></ul><ul><li>Example computation </li></ul><ul><ul><li>fact(3,1) = fact(2, 3) was fact(2,  y.3*y) </li></ul></ul><ul><ul><li>= fact(1, 6) was fact(1,  x.6*x) </li></ul></ul><ul><ul><li>= 6 </li></ul></ul>
  35. 35. Other uses for continuations <ul><li>Explicit control </li></ul><ul><ul><li>Normal termination -- call continuation </li></ul></ul><ul><ul><li>Abnormal termination -- do something else </li></ul></ul><ul><li>Compilation techniques </li></ul><ul><ul><li>Call to continuation is functional form of “go to” </li></ul></ul><ul><ul><li>Continuation-passing style makes control flow explicit </li></ul></ul><ul><li>MacQueen: “Callcc is the closest thing to a </li></ul><ul><li>‘ come-from’ statement I’ve ever seen.” </li></ul>
  36. 36. Theme Song: Charlie on the MTA <ul><li>Let me tell you the story Of a man named Charlie On a tragic and fateful day He put ten cents in his pocket, Kissed his wife and family Went to ride on the MTA </li></ul><ul><li>Charlie handed in his dime At the Kendall Square Station And he changed for Jamaica Plain When he got there the conductor told him, &quot;One more nickel.&quot; Charlie could not get off that train. </li></ul><ul><li>Chorus:                         Did he ever return,                         No he never returned                         And his fate is still unlearn'd                         He may ride forever                         'neath the streets of Boston                         He's the man who never returned. </li></ul>
  37. 37. Capturing Current Continuation <ul><li>Language feature (use open SMLofNJ; on Leland) </li></ul><ul><ul><li>callcc : call a function with current continuation </li></ul></ul><ul><ul><li>Can be used to abort subcomputation and go on </li></ul></ul><ul><li>Examples </li></ul><ul><ul><li>callcc (fn k => 1); </li></ul></ul><ul><ul><li>> val it = 1 : int </li></ul></ul><ul><ul><ul><li>Current continuation is “fn x => print x” </li></ul></ul></ul><ul><ul><ul><li>Continuation is not used in expression </li></ul></ul></ul><ul><ul><li>1 + callcc(fn k => 5 + throw k 2); </li></ul></ul><ul><ul><li>> val it = 3 : int </li></ul></ul><ul><ul><ul><li>Current continuation is “fn x => print 1+x” </li></ul></ul></ul><ul><ul><ul><li>Subexpression throw k 2 applies continuation to 2 </li></ul></ul></ul>skip callcc, at least for now
  38. 38. More with callcc <ul><li>Example </li></ul><ul><ul><li>1 + callcc(fn k1=> … </li></ul></ul><ul><ul><li>callcc(fn k2 => … </li></ul></ul><ul><ul><li>if … then (throw k1 0) </li></ul></ul><ul><ul><li>else (throw k2 “stuck”) </li></ul></ul><ul><ul><li>)) </li></ul></ul><ul><li>Intuition </li></ul><ul><ul><li>Callcc lets you mark a point in program that you can return to </li></ul></ul><ul><ul><li>Throw lets you jump to that point and continue from there </li></ul></ul>
  39. 39. Example <ul><li>Pass two continuations and choose one </li></ul><ul><ul><li>fun f(x,k1,k2) = 3 + (if x>0 then throw k1(x) </li></ul></ul><ul><ul><li>else throw k2(x)); </li></ul></ul><ul><ul><li>fun g(y,k1) = 2 + callcc(fn k2 => f(y,k1,k2)); </li></ul></ul><ul><ul><li>fun h(z) = 1 + callcc(fn k1 => g(z+1,k1)); </li></ul></ul><ul><ul><li>h(1); </li></ul></ul><ul><ul><li>h(~2); </li></ul></ul>Answers: h(1)  3 h(~2)  2
  40. 40. Continuations in Mach OS <ul><li>OS kernel schedules multiple threads </li></ul><ul><ul><li>Each thread may have a separate stack </li></ul></ul><ul><ul><li>Stack of blocked thread is stored within the kernel </li></ul></ul><ul><li>Mach “continuation” approach </li></ul><ul><ul><li>Blocked thread represented as </li></ul></ul><ul><ul><ul><li>Pointer to a continuation function, list of arguments </li></ul></ul></ul><ul><ul><ul><li>Stack is discarded when thread blocks </li></ul></ul></ul><ul><ul><li>Programming implications </li></ul></ul><ul><ul><ul><li>Sys call such as msg_recv can block </li></ul></ul></ul><ul><ul><ul><li>Kernel code calls msg_recv with continuation passed as arg </li></ul></ul></ul><ul><ul><li>Advantage/Disadvantage </li></ul></ul><ul><ul><ul><li>Saves a lot of space, need to write “continuation” functions </li></ul></ul></ul>
  41. 41. “ Continuations” in Web programming <ul><li>XMLHttpRequest similar to callcc: </li></ul><ul><ul><li>function callcc(url) { </li></ul></ul><ul><ul><li> var xhr = new XMLHttpRequest(); </li></ul></ul><ul><ul><li> xhr.open('GET', url, false ); </li></ul></ul><ul><ul><li> xhr.send(null); </li></ul></ul><ul><ul><li> return xhr.responseText; </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>Usage: alert(callcc('http://a.com/describe?id=10')); </li></ul><ul><li>Server invokes continuation by sending a response </li></ul><ul><li>Unfortunately, this pauses client while server runs </li></ul>
  42. 42. “ Continuations” in Web programming <ul><li>Asynchronous XHR also similar to continuations: </li></ul><ul><ul><li>function callWithContinuation(url, k ) { </li></ul></ul><ul><ul><li> var xhr = new XMLHttpRequest(); </li></ul></ul><ul><ul><li> xhr.open('GET', url, true ); </li></ul></ul><ul><ul><li> xhr.onreadystatechange = function () { </li></ul></ul><ul><ul><li> if (xhr.readyState == 4) </li></ul></ul><ul><ul><li> k (xhr.responseText); </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> xhr.send(null); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>Usage: callWithContinuation('http://a.com/describe?id=10', alert); </li></ul><ul><li>Client continues while server runs </li></ul><ul><li>Basis of AJAX Web programming paradigm </li></ul>
  43. 43. Continuations in compilation <ul><li>SML continuation-based compiler [Appel, Steele] </li></ul><ul><ul><li>1) Lexical analysis, parsing, type checking </li></ul></ul><ul><ul><li>2) Translation to  -calculus form </li></ul></ul><ul><ul><li>3) Conversion to continuation-passing style (CPS) </li></ul></ul><ul><ul><li>4) Optimization of CPS </li></ul></ul><ul><ul><li>5) Closure conversion – eliminate free variables </li></ul></ul><ul><ul><li>6) Elimination of nested scopes </li></ul></ul><ul><ul><li>7) Register spilling – no expression with >n free vars </li></ul></ul><ul><ul><li>8) Generation of target assembly language program </li></ul></ul><ul><ul><li>9) Assembly to produce target-machine program </li></ul></ul>
  44. 44. Coroutines (this is complicated…) <ul><ul><li>datatype tree = leaf of int | node of tree*tree; </li></ul></ul><ul><ul><li>datatype coA = A of (int* coB) cont (* searchA wants int and B-cont*) </li></ul></ul><ul><ul><li>and coB = B of coA cont; (* searchB wants an A-continuation *) </li></ul></ul><ul><ul><li>fun resumeA(x, A k) = callcc(fn k' => throw k (x, B k')); </li></ul></ul><ul><ul><li>fun resumeB( B k) = callcc(fn k' => throw k (A k')); </li></ul></ul><ul><ul><li>exception DISAGREE; exception DONE; </li></ul></ul><ul><ul><li>fun searchA(leaf(x),(y, other: coB)) = </li></ul></ul><ul><ul><li>if x=y then resumeB(other) else raise DISAGREE </li></ul></ul><ul><ul><li>| searchA(node(t1,t2), other) = searchA(t2, searchA(t1, other)); </li></ul></ul><ul><ul><li>fun searchB(leaf(x), other : coA) = resumeA(x,other) </li></ul></ul><ul><ul><li>| searchB(node(t1,t2), other) = searchB(t2, searchB(t1, other)); </li></ul></ul><ul><ul><li>fun startB(t: tree) = callcc(fn k => (searchB(t, A k); raise DONE)); </li></ul></ul><ul><ul><li>fun compare(t1,t2) = searchA(t1, startB(t2)); </li></ul></ul>skip callcc, at least for now
  45. 45. Summary <ul><li>Structured Programming </li></ul><ul><ul><li>Go to considered harmful </li></ul></ul><ul><li>Exceptions </li></ul><ul><ul><li>“ structured” jumps that may return a value </li></ul></ul><ul><ul><li>dynamic scoping of exception handler </li></ul></ul><ul><li>Continuations </li></ul><ul><ul><li>Function representing the rest of the program </li></ul></ul><ul><ul><li>Generalized form of tail recursion </li></ul></ul><ul><ul><li>Used in Lisp and ML compilation, some OS projects, web application development, … </li></ul></ul>
  46. 46. What is a functional language ? <ul><li>“ No side effects” </li></ul><ul><li>OK, we have side effects, but we also have higher-order functions… </li></ul><ul><li>We will use pure functional language to mean </li></ul><ul><li>“ a language with functions, but without side effects </li></ul><ul><li>or other imperative features.” </li></ul>
  47. 47. No-side-effects language test <ul><li>Within the scope of specific declarations of x 1 ,x 2 , …, x n , all occurrences of an expression e containing only variables x 1 ,x 2 , …, x n , must have the same value. </li></ul><ul><li>Example </li></ul><ul><ul><li>begin </li></ul></ul><ul><ul><li>integer x=3; integer y=4; </li></ul></ul><ul><ul><li>5*(x+y)-3 </li></ul></ul><ul><ul><li>… // no new declaration of x or y // </li></ul></ul><ul><ul><li>4*(x+y)+1 </li></ul></ul><ul><ul><li>end </li></ul></ul>?
  48. 48. Example languages <ul><li>Pure Lisp </li></ul><ul><ul><li>atom, eq, car, cdr, cons, lambda, define </li></ul></ul><ul><li>Impure Lisp: rplaca, rplacd </li></ul><ul><ul><li>lambda (x) (cons </li></ul></ul><ul><ul><li>(car x) </li></ul></ul><ul><ul><li>(… (rplaca (… x …) ...) ... (car x) … ) </li></ul></ul><ul><ul><li>)) </li></ul></ul><ul><ul><li>Cannot just evaluate (car x) once </li></ul></ul><ul><li>Common procedural languages are not functional </li></ul><ul><ul><li>Pascal, C, Ada, C++, Java, Modula, … </li></ul></ul><ul><ul><li>Example functional programs in a couple of slides </li></ul></ul>
  49. 49. Backus’ Turing Award <ul><li>John Backus was designer of Fortran, BNF, etc. </li></ul><ul><li>Turing Award in 1977 </li></ul><ul><li>Turing Award Lecture </li></ul><ul><ul><li>Functional prog better than imperative programming </li></ul></ul><ul><ul><li>Easier to reason about functional programs </li></ul></ul><ul><ul><li>More efficient due to parallelism </li></ul></ul><ul><ul><li>Algebraic laws </li></ul></ul><ul><ul><ul><li>Reason about programs </li></ul></ul></ul><ul><ul><ul><li>Optimizing compilers </li></ul></ul></ul>
  50. 50. Reasoning about programs <ul><li>To prove a program correct, </li></ul><ul><ul><li>must consider everything a program depends on </li></ul></ul><ul><li>In functional programs, </li></ul><ul><ul><li>dependence on any data structure is explicit </li></ul></ul><ul><li>Therefore, </li></ul><ul><ul><li>easier to reason about functional programs </li></ul></ul><ul><li>Do you believe this? </li></ul><ul><ul><li>This thesis must be tested in practice </li></ul></ul><ul><ul><li>Many who prove properties of programs believe this </li></ul></ul><ul><ul><li>Not many people really prove their code correct </li></ul></ul>
  51. 51. Haskell Quicksort <ul><li>Very succinct program </li></ul><ul><ul><li>qsort [] = [] </li></ul></ul><ul><ul><li>qsort (x:xs) = qsort elts_lt_x ++ [x] </li></ul></ul><ul><ul><li>++ qsort elts_greq_x </li></ul></ul><ul><ul><li>where elts_lt_x = [y | y <- xs, y < x] </li></ul></ul><ul><ul><li>elts_greq_x = [y | y <- xs, y >= x] </li></ul></ul><ul><li>This is the whole thing </li></ul><ul><ul><li>No assignment – just write expression for sorted list </li></ul></ul><ul><ul><li>No array indices, no pointers, no memory management, … </li></ul></ul>
  52. 52. Compare: C quicksort <ul><ul><li>qsort( a, lo, hi ) int a[], hi, lo; </li></ul></ul><ul><ul><li>{ int h, l, p, t; </li></ul></ul><ul><ul><li>if (lo < hi) { </li></ul></ul><ul><ul><li>l = lo; h = hi; p = a[hi]; </li></ul></ul><ul><ul><li>do { </li></ul></ul><ul><ul><li>while ((l < h) && (a[l] <= p)) l = l+1; </li></ul></ul><ul><ul><li>while ((h > l) && (a[h] >= p)) h = h-1; </li></ul></ul><ul><ul><li>if (l < h) { t = a[l]; a[l] = a[h]; a[h] = t; } </li></ul></ul><ul><ul><li>} while (l < h); </li></ul></ul><ul><ul><li>t = a[l]; a[l] = a[hi]; a[hi] = t; </li></ul></ul><ul><ul><li>qsort( a, lo, l-1 ); </li></ul></ul><ul><ul><li>qsort( a, l+1, hi ); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>} </li></ul></ul>
  53. 53. Interesting case study <ul><li>Naval Center programming experiment </li></ul><ul><ul><li>Separate teams worked on separate languages </li></ul></ul><ul><ul><li>Surprising differences </li></ul></ul><ul><ul><li>Some programs were incomplete or did not run </li></ul></ul><ul><ul><li>Many evaluators didn’t understand, when shown the code, that the Haskell program was complete. They thought it was a high level partial specification. </li></ul></ul>Hudak and Jones, Haskell vs Ada vs C++ vs Awk vs …, Yale University Tech Report, 1994
  54. 54. Disadvantages of Functional Prog <ul><li>Functional programs often less efficient. Why? </li></ul><ul><li>Change 3rd element of list x to y </li></ul><ul><ul><li>(cons (car x) (cons (cadr x) (cons y (cdddr x)))) </li></ul></ul><ul><ul><ul><li>Build new cells for first three elements of list </li></ul></ul></ul><ul><ul><li>(rplaca (cddr x) y) </li></ul></ul><ul><ul><ul><li>Change contents of third cell of list directly </li></ul></ul></ul><ul><li>However, many optimizations are possible </li></ul>A B C D
  55. 55. Von Neumann bottleneck <ul><li>Von Neumann </li></ul><ul><ul><li>Mathematician responsible for idea of stored program </li></ul></ul><ul><li>Von Neumann Bottleneck </li></ul><ul><ul><li>Backus’ term for limitation in CPU-memory transfer </li></ul></ul><ul><li>Related to sequentiality of imperative languages </li></ul><ul><ul><li>Code must be executed in specific order </li></ul></ul><ul><ul><ul><li>function f(x) { if (x<y) then y = x; else x = y; } </li></ul></ul></ul><ul><ul><ul><li>g( f(i), f(j) ); </li></ul></ul></ul>
  56. 56. Eliminating VN Bottleneck <ul><li>No side effects </li></ul><ul><ul><li>Evaluate subexpressions independently </li></ul></ul><ul><ul><li>Example </li></ul></ul><ul><ul><ul><li>function f(x) { return x<y ? 1 : 2; } </li></ul></ul></ul><ul><ul><ul><li>g(f(i), f(j), f(k), … ); </li></ul></ul></ul><ul><li>Does this work in practice? Good idea but ... </li></ul><ul><ul><li>Too much parallelism </li></ul></ul><ul><ul><li>Little help in allocation of processors to processes </li></ul></ul><ul><ul><li>... </li></ul></ul><ul><ul><li>David Shaw promised to build the non-Von ... </li></ul></ul><ul><li>Effective, easy concurrency is a hard problem </li></ul>

×