1 / 15

Standard ML

Standard ML. Exceptions. Exceptions – The Need. An extensive part of the code is error handling A function can return an answer, or fail to find one, or signal that a solution does not exist. We can try to use ML datatypes:’ datatype int sol = Success of int | Failure | Impossible

primo
Download Presentation

Standard ML

An Image/Link below is provided (as is) to download presentation 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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Standard ML Exceptions

  2. Exceptions – The Need • An extensive part of the code is error handling • A function can return an answer, or fail to find one, or signal that a solution does not exist. • We can try to use ML datatypes:’ datatype int sol = Success of int | Failure | Impossible • Using special return values can be tedious, and requires explicit handling every time casemethodA problem of Success s => Int.toString s | Failure => (casemethodB problem of Success s => Int.toString s | Failure => "Both failed" | Impossible => "No Good") | Impossible => "No Good“ • Sometimes we don’t really know what to do with the error, so we we’ll return a sol…

  3. Using Exceptions • Separates the exceptional path from the normal path • Upon error, we raise an exception funhd [] = raise Empty | hd (x::xs) = x • A raised exception is called packet • The packet propagates … fun add_hd xsys = (hdxs) + (hdys) • … up to the first point where a handlerfor it exists val x = add_hd [1] [] handle Empty => 1 • The caller of a function doesn’t have to check any of the error values • The whole expression is a single expression

  4. The Exception type exn • We can raise only a specific type: the built-in type exn • The type exn is a special datatype with an extendable set of constructors and values • Declaring exceptions - values of type exn - exceptionFailure; - Failure; val it = Failure(-) : exn • Declaring exceptions – Constructors: - exceptionProblemof int; - Problem; val it = fn : int -> exn

  5. The Exception type exn • In normal expressions, exn behaves pretty much like a regular datatype (though it is not an equality type) • Values of type exn have all the privileges of values of other types - val x = Failure; (* Failure is a value *) val x = Failure(-) : exn - val p = Problem 1; (* Problem is a constructor *) val p = Problem(-) : exn - map Problem [0, 1, 2]; val it = [Problem(-),Problem(-),Problem(-)] : exn list - fun what's_the_problem (Problem p) = p; Warning: match nonexhaustive Problem x => ... val what's_the_problem = fn : exn -> int

  6. Raising Exceptions - Semantics • raise Exp • The expression Exp of type exn is evaluated to e • raise Exp evaluates to an exception packetcontaining e • Packets are not ML values • Packets propagates under the call-by-value rule • Which means that all of the following evaluate toraise Exp • f (raise Exp) • (raise Exp) arg • raise (Exp1 (raise Exp)) (* Exp1 is constructor *) • (raise Exp, raise Exp1) (* or {a=Exp, b=Exp1} *) • letval name = raise Exp insome_expressionend • localval name = raise Exp insome_declarationend

  7. The Computation of take fun take (0, _) = [] | take (n, x::xs) = x :: take (n-1, xs) | take (n, nil) = raise Empty • fun reverse3 xs = rev (take (3, xs)) • reverse3 [1,2] • rev (take (3, [1, 2])) • rev (1::take (2, [2])) • rev (1::(2::take (1, []))) • rev (1::(2::raise Empty)) • rev (1::raise Empty) • rev (raise Empty) • raise Empty

  8. Handling Exceptions - Syntax • General form: Exp_0handleP1 => Exp_1| . . .|Pn => Exp_n • Assuming Pis are disjoint, this is equivalent to (((Exp_0handleP1 => Exp_1) … ) handle Pn => Exp_n) • All Exp_i must be type-compatible • All Pi must be valid pattern for the type exn • Calculating length using exceptions - fun len l = 1 + len (tl l) handle Empty => 0;

  9. Handling Exceptions - Semantics Exp_0handleCons1 x => Exp_1 • Assume Exp_0 evaluates to some value V Then the value of this expression is: • Exp1 If Exp_0 evaluate to raise Cons1 x • V otherwise. V may be either a normal value, or a non-matching raised exception. • Handle is a short-circuit operator, like if-then-else • All this is exactly equivalent to the familiar notions from C++

  10. The Computation of len • funtl [] = raiseTl | tl (x::xs) = xs • fun len xs = 1 + (len (tlxs)) handle Tl => 0; • len [3] • 1+(len (tl [3])) handle Tl=>0 • 1+(len []) handle Tl=>0 • 1+(1+(len (tl [])) handle Tl=>0) handle Tl=>0 • 1+(1+(len (raise Tl)) handle Tl=>0) handle Tl=>0 • 1+(1+(raise Tl) handle Tl=>0) handle Tl=>0 • 1+(raise Tl handle Tl=>0) handle Tl=>0 • 1+0 handle Tl=>0 • 1 handle Tl=>0 • 1

  11. The Type of raise Exp • The expression raise Exp is of type ‘a • Technically described as “t for some arbitrary type t” • It is NOT an expression of type exn! • Within context, it simply puts no restriction on other parts of the expression: - fun throw _ = raise Empty; val throw = fn : 'a -> 'b - fun bar x = if x>0 then x elseraise Underflow; val bar = fn : int -> int • Theoretically, It may be type-checked as type None (aka Bot) or something similar to datatype ‘a Ex = ‘a

  12. Using Exception Handling - More • Example: If methodA fails then methodB is tried casemethodA problem of Success s => Int.toString s | Failure => (casemethodB problem of Success s => Int.toString s | Failure => "Both failed" | Impossible => "No Good") | Impossible => "No Good" • Exceptions give a shorter and clearer program. Error propagation does not clutter the code. toString (methodA problem handle Failure => methodB problem)handle Failure => "Both failed“ | Impossible => "No Good"

  13. Error Messages - raise Problem; Error: argument of raise is not an exception [tycon mismatch] raised: int -> exn in expression: raise Problem • hd [“good”] handle nil => “bad”; Error: handler domain is not exn [tycon mismatch] handler domain: 'Z list in expression: hd ("good" :: nil) handle nil => "bad" | exn => raise exn

  14. Exam Questions • What is the response • local exception E of string; in fun f (E “Hello”, E x) = x; end letexceptionExyof int in (fn 2 => raise Exy 4 | x => x+x) 2 handle Exy n => n end

  15. Standard Exceptions Some built-in exceptions • Chr is raised by (chr k) if k<0 or k>255 • Match is raised for failure of pattern-matching. e.g. when an argument matches none of the function’s patterns, if a case expression has no pattern that matches, etc. • Bind is raised if the value of E does not match pattern P in the declaration val P = E

More Related