1
play

1 ML Example C++ Example exception Determinant; (* declare - PDF document

CS 242 Topics Control in Sequential Languages Structured Programming Go to considered harmful Exceptions structured jumps that may return a value John Mitchell dynamic scoping of exception handler Continuations


  1. CS 242 Topics Control in Sequential Languages � Structured Programming • Go to considered harmful � Exceptions • “structured” jumps that may return a value John Mitchell • dynamic scoping of exception handler � Continuations • Function representing the rest of the program • Generalized form of tail recursion � Control of evaluation order (force and delay) • May not cover in lecture. Book section straightforward. Fortran Control Structure Historical Debate 10 IF (X .GT. 0.000001) GO TO 20 � Dijkstra, Go To Statement Considered Harmful 11 X = -X • Letter to Editor, C ACM , March 1968 IF (X .LT. 0.000001) GO TO 50 • Link on CS242 web site 20 IF (X*Y .LT. 0.00001) GO TO 30 � Knuth, Structured Prog. with go to Statements X = X-Y-Y 30 X = X+Y • You can use goto, but do so in structured way … ... � Continued discussion 50 CONTINUE • Welch, “GOTO (Considered Harmful) n , n is Odd” X = A Y = B-A � General questions GO TO 11 • Do syntactic rules force good programming style? … • Can they help? Similar structure may occur in assembly code Advance in Computer Science Exceptions: Structured Exit � Standard constructs that structure jumps � Terminate part of computation if … then … else … end • Jump out of construct while … do … end • Pass data as part of jump for … { … } • Return to most recent site set up to handle exception case … • Unnecessary activation records may be deallocated � Modern style – May need to free heap space, other resources � Two main language constructs • Group code in logical blocks • Declaration to establish exception handler • Avoid explicit jumps except for function return • Statement or expression to raise or throw exception • Cannot jump into middle of block or function body Often used for unusual or exceptional condition, but not necessarily 1

  2. ML Example C++ Example exception Determinant; (* declare exception name *) Matrix invert(Matrix m) { fun invert (M) = (* function to invert matrix *) if … throw Determinant; … … if … }; then raise Determinant (* exit if Det=0 *) else … try { … invert(myMatrix); … end; } ... catch (Determinant) { … invert (myMatrix) handle Determinant => … ; // recover from error } Value for expression if determinant of myMatrix is 0 C++ vs ML Exceptions ML Exceptions � C++ exceptions � Declaration • Can throw any type exception 〈 name 〉 of 〈 type 〉 • Stroustrup: “I prefer to define types with no other purpose gives name of exception and type of data passed when raised than exception handling. This minimizes confusion about their � Raise purpose. In particular, I never use a built-in type, such as int, as raise 〈 name 〉 〈 parameters 〉 an exception.” -- The C++ Programming Language, 3 rd ed. expression form to raise and exception and pass data � ML exceptions � Handler • Exceptions are a different kind of entity than types. 〈 exp1 〉 handle 〈 pattern 〉 => 〈 exp2 〉 • Declare exceptions before use evaluate first expression Similar, but ML requires the recommended C++ style. if exception that matches pattern is raised, then evaluate second expression instead General form allows multiple patterns. Which handler is used? Exception for Error Condition exception Ovflw; - datatype ‘a tree = LF of ‘a | ND of (‘a tree)*(‘a tree) fun reciprocal(x) = - exception No_Subtree; if x<min then raise Ovflw else 1/x; - fun lsub (LF x) = raise No_Subtree (reciprocal(x) handle Ovflw=>0) / (reciprocal(y) handle Ovflw=>1); | lsub (ND(x,y)) = x; � Dynamic scoping of handlers > val lsub = fn : ‘a tree -> ‘a tree • First call handles exception one way • Second call handles exception another • This function raises an exception when there is no • General dynamic scoping rule reasonable value to return Jump to most recently established handler on run-time stack • We’ll look at typing later. � Dynamic scoping is not an accident • User knows how to handler error • Author of library function does not 2

  3. Exception for Efficiency Dynamic Scope of Handler � Function to multiply values of tree leaves exception X; fun prod(LF x) = x (let fun f(y) = raise X | prod(ND(x,y)) = prod(x) * prod(y); and g(h) = h(1) handle X => 2 scope � Optimize using exception in fun prod(tree) = g(f) handle X => 4 let exception Zero end) handle X => 6; fun p(LF x) = if x=0 then (raise Zero) else x handler | p(ND(x,y)) = p(x) * p(y) in Which handler is used? p(tree) handle Zero=>0 end; Dynamic Scope of Handler Compare to static scope of variables exception X; handler X 6 exception X; val x=6; (let fun f(y) = raise X access link (let fun f(y) = raise X (let fun f(y) = x and g(h) = h(1) handle X => 2 fun f and g(h) = h(1) and g(h) = let val x=2 in in access link handle X => 2 h(1) g(f) handle X => 4 fun g end) handle X => 6; in in access link g(f) handle X => 4 let val x=4 in g(f) handler X 4 end) handle X => 6; end); Dynamic scope: g(f) access link find first X handler, formal h going up the handler X 2 dynamic call chain leading to raise X. access link f(1) formal y 1 Static Scope of Declarations Typing of Exceptions val x=6; val x 6 � Typing of raise 〈 exn 〉 (let fun f(y) = x access link • Recall definition of typing and g(h) = let val x=2 in fun f – Expression e has type t if normal termination of e h(1) produces value of type t access link in • Raising exception is not normal termination fun g let val x=4 in g(f) – Example: 1 + raise X end); access link � Typing of handle 〈 exn 〉 => 〈 value 〉 val x 4 Static scope: find • Converts exception to normal termination g(f) access link first x, following formal h • Need type agreement access links from val x 2 • Examples the reference to X. access link – 1 + ((raise X) handle X => e) Type of e must be int f(1) formal y 1 – 1 + (e 1 handle X => e 2 ) Type of e 1, e 2 must be int 3

  4. Exceptions and Resource Allocation Continuations exception X; � Resources may be � What’s the idea? allocated between (let • Stop, and then continue handler and raise val x = ref [1,2,3] in � May be “garbage” � In other words, let after exception • The continuation of an expression in a program is the val y = ref [4,5,6] � Examples remaining actions to perform after evaluating the in • Memory expression … raise X • Lock on database end • Threads Important: does not depend on the expression, end); handle X => ... • … only the program that contains it. General problem: no obvious solution Continuations Example of Continuation Concept � Idea: � Expression • The continuation of an expression is “the remaining • 2*x + 3*y + 1/x + 2/y work to be done after evaluating the expression” � What is continuation of 1/x? • Continuation of e is a function applied to e • Remaining computation after division � General programming technique • Capture the continuation at some point in a program let val before = 2*x + 3*y • Use it later: “jump” or “exit” by function call fun continue(d) = before + d + 2/y � Useful in in • Compiler optimization: make control flow explicit continue (1/x) • Operating system scheduling, multiprogramming end • Web site design Example: Tail Recursive Factorial Continuation view of factorial � Standard recursive function fact(n) = if n=0 then 1 else n*fact(n-1) fact(n) = if n=0 then 1 else n*fact(n-1) return • This invocation multiplies by 9 fact(9) � Tail recursive and returns n 9 f(n,k) = if n=0 then k else f(n-1, n*k) • Continuation of fact(8) is λ x. 9*x ... fact(n) = f(n,1) return • Multiplies by 8 and returns fact(8) � How could we derive this? n 8 • Continuation of fact(7) is • Transform to continuation-passing form λ y. ( λ x. 9*x) (8*y) ... • Optimize continuation functions to single integer return • Multiplies by 7 and returns fact(7) n 7 • Continuation of fact(6) is ... λ z. ( λ y. ( λ x. 9*x) (8*y)) (7*z) 4

Recommend


More recommend