Annotation of researchv10no/cmd/sml/doc/refman/exceptions.tex, revision 1.1

1.1     ! root        1: \chapter{Exceptions}
        !             2: \label{exception}
        !             3: The rough and ready rule for understanding how exceptions are handled
        !             4: is as follows.  If an exception is raised by a \verb"raise"
        !             5: expression
        !             6: \begin{quote}
        !             7: \verb"raise" $E$ \verb"(" {\it exp} \verb")"
        !             8: \end{quote}
        !             9: which lies in the textual scope of a declaration of the exception
        !            10: constructor $E$, then it may be handled by a handling rule
        !            11: \begin{quote}
        !            12: \verb"handle" $E$ \verb"(" {\it pat} \verb") =>" {\it exp'}
        !            13: \end{quote}
        !            14: but only if this handler is in the textual scope of the same
        !            15: declaration.
        !            16: 
        !            17: Any exception, regardless of scope, is handled by a wildcard or
        !            18: variable pattern, as
        !            19: \begin{quote}
        !            20: \verb"handle _ =>" {\it exp'}
        !            21: \end{quote}
        !            22: This rule is perfectly adequate for exceptions declared at top level;
        !            23: some examples in Section~\ref{pathexn} below illustrate what may occur in other
        !            24: cases.
        !            25: 
        !            26: \section{An example}
        !            27: To illustrate the generality of exception handling,  suppose we have
        !            28: declared some exceptions as follows:
        !            29: \begin{verbatim}
        !            30: exception    Oddlist of int    and   Oddstring of string
        !            31: \end{verbatim}
        !            32: and that a certain expression  exp:int  may raise either of these
        !            33: exceptions and also runs the risk of dividing by zero.  The handler
        !            34: in the following \verb"handle" expression would deal with these
        !            35: expressions:
        !            36: \begin{verbatim}
        !            37: exp handle Oddlist []  => 0
        !            38:          | Oddlist [x] => 2*x
        !            39:          | Oddlist (x::y::_) => x div y
        !            40:          | Oddstring "" => 0
        !            41:          | Oddstring s => size(s)-1
        !            42:          | Div => 10000
        !            43: \end{verbatim}
        !            44: Note that the whole expression is well-typed because in each handling
        !            45: rule the type of the match-pattern is \verb"exn", and because the
        !            46: result type of the match is \verb"int", the same as the type of exp.
        !            47: 
        !            48: Note also that the last handling rule will handle \verb"Div"
        !            49: exceptions raised by exp, but will not handle the \verb"Div"
        !            50: exception that may be raised by \verb"x div y" in the third handling
        !            51: rule.  Finally, note that a universal handling rule
        !            52: \begin{verbatim}
        !            53:          | _ => 50000
        !            54: \end{verbatim}
        !            55: at the end would deal with all other exceptions raised by  exp.
        !            56: 
        !            57: \section{Exception constructors}
        !            58: For an exception constructor E, the expression
        !            59: \begin{quote}
        !            60: $E$ \verb"(" {\it exp} \verb")"
        !            61: \end{quote}
        !            62: evaluates the expression {\it exp}, producing value $v$,
        !            63: and then applies the constructor $E$ to it, yielding the value
        !            64: $E(v)$, whose type is \verb"exn".
        !            65: 
        !            66: The \verb"raise" keyword may be applied to any expression of type
        !            67: \verb"exn", and has the effect of ``raising'' that exception value.
        !            68: The innermost (dynamically) enclosing expression 
        !            69: $e = e_1~\verb"handle"~m_1$ is found; all further evaluation of the
        !            70: expression $e_1$ (and its subphrases) is aborted; and the match $m_1$
        !            71: is applied to the exception value, yielding  the result of the
        !            72: expression $e$.  
        !            73: 
        !            74: If the match in a handler fails, then the exception value is
        !            75: \label{reraise}
        !            76: re-raised, and another enclosing handler is found.
        !            77: 
        !            78: Exception constructors may be nullary (have no associated value), in
        !            79: which case the {\it exp} and {\it pat} in the previous discussion are
        !            80: omitted.
        !            81: 
        !            82: Exceptions may be constructed independently of raising them:
        !            83: \begin{verbatim}
        !            84:   exception A of int
        !            85:   val e = A 6
        !            86:   val x = raise e
        !            87: \end{verbatim}
        !            88: Handlers may be abstracted from the \verb"handle" keyword:
        !            89: \begin{verbatim}
        !            90:    val h = fn E 0 => "zero"
        !            91:             | E _ => "nonzero"
        !            92:             | v => raise v
        !            93: 
        !            94:    f(x)  handle  e => h e
        !            95: \end{verbatim}
        !            96: Note that it is advisable in this case to have a default clause in
        !            97: the function \verb"h", since the default for a \verb"handle" match
        !            98: (re-raising the exception) is different from the default for a \verb"fn" or
        !            99: \verb"case" match (raising the \verb"Match" exception).
        !           100: 
        !           101: The ordinary wildcard pattern 
        !           102: \verb"_" will handle any exception when it is used in a pattern, as
        !           103: will any pattern consisting solely of a variable.  These should be
        !           104: used with some care, bearing in mind that they will even handle
        !           105: interrupts.
        !           106: 
        !           107: Nullary exception names, when misspelled, appear to the compiler to be
        !           108: variables; these will then match any exception.  For this reason we
        !           109: recommend the convention that exception names (and other
        !           110: constructors) be written beginning with an uppercase character, and
        !           111: variables be written beginning with a lowercase character.  The
        !           112: compiler may remind the programmer of this convention when it is
        !           113: violated.
        !           114: 
        !           115: \section{Some pathological examples}
        !           116: \label{pathexn}
        !           117: We now consider some possible misuses of exception handling, which
        !           118: may arise from the fact that exception declarations have scope, and
        !           119: that each evaluation of a generative exception binding creates a
        !           120: distinct exception.  Consider a simple example:
        !           121: \begin{verbatim}
        !           122: exception  E of bool
        !           123: fun f(x) = 
        !           124:      let exception E of int
        !           125:       in if x > 100 then raise E(x) else x+1
        !           126:      end
        !           127: val z = f(200) handle E(true) => 500 | E(false) => 1000
        !           128: \end{verbatim}
        !           129: The program is  well-typed, but useless.  The exception bound to the
        !           130: outer \verb"E" is distinct from that bound to the inner \verb"E";
        !           131: thus the exception raised by \verb"f(200)", with excepted value 200,
        !           132: could only be handled by a handler within the scope of the inner
        !           133: exception declaration---it will not be handled by the handler in the
        !           134: program, which expects a boolean value.  So this exception will be
        !           135: reported at top level.  This would apply even if the outer exception
        !           136: declaration were also of type int; the two exceptions bound to
        !           137: \verb"E" would be distinct.
        !           138: 
        !           139: On the other hand, if the last line of the program is changed to
        !           140: \begin{verbatim}
        !           141: f(200) handle _ => 500
        !           142: \end{verbatim}
        !           143: then the exception will be caught, and the value 500 returned.  A
        !           144: universal handling rule (i.e. \verb"_" or a variable-identifier)
        !           145: catches any exception---even one exported from the scope of the
        !           146: declaration of the associated exception name---but cannot examine the
        !           147: excepted value carried by the exception constructor, since the type
        !           148: of this value cannot be statically determined.
        !           149: 
        !           150: Even a single textual exception binding---if for example it is
        !           151: declared within a recursively defined function---may bind distinct
        !           152: exceptions to the same identifier.  Consider another useless program:
        !           153: \begin{verbatim}
        !           154: fun f(x) =
        !           155:      let exception E
        !           156:       in if p(x) then a(x)
        !           157:                  else if q(x) then f(b(x)) handle E => c(x)
        !           158:                               else raise E
        !           159:      end
        !           160: val z = f v
        !           161: \end{verbatim}
        !           162: Now if p(v) is false but q(v) is true, the recursive call will
        !           163: evaluate f(b(v)).  Then if both p(b(v) and q(b(v)) are false, this
        !           164: evaluation will raise \verb"E".  But this exception will not be
        !           165: handled, since the exception raised is that which is bound to
        !           166: \verb"E" by the inner---not outer---evaluation of the exception
        !           167: declaration.
        !           168: 
        !           169: These pathological examples should not leave the impression that
        !           170: exceptions are hard to use or to understand.  The rough and ready
        !           171: rule of Section~\ref{exception} will almost always  give the correct
        !           172: understanding.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.