Skip to main content
Engineering LibreTexts

12.11: Exceptions and ensure, ifCurtailed Interaction

  • Page ID
    45969
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Now that we saw how exceptions work, we present the interplay between exceptions and the ensure: and ifCurtailed: semantics. Exception handlers are executed then ensure: or ifCurtailed: blocks are executed. ensure: argument is always executed while ifCurtailed: argument is only executed when its receiver execution led to an unwound stack.

    The following example shows such behavior. It prints: should show first error followed by then should show curtailed and returns 4.

    [[ 1/0 ]
        ifCurtailed: [ Transcript show: 'then should show curtailed'; cr. 6 ]]
        on: Error do: [ :e |
            Transcript show: 'should show first error'; cr.
            e return: 4 ].
    

    First the [1/0] raises a division by zero error. This error is handled by the exception handler. It prints the first message. Then it returns the value 4 and since the receiver raised an error, the argument of the ifCurtailed: message is evaluated: it prints the second message. Note that ifCurtailed: does not change the return value expressed by the error handler or the ifCurtailed: argument.

    The following expression shows that when the stack is not unwound the expression value is simply returned and none of the handlers are executed. 1 is returned.

    [[ 1 ]
            ifCurtailed: [ Transcript show: 'curtailed'; cr. 6 "does not display it" ]]
        on: Error do: [ :e |
            Transcript show: 'error'; cr. "does not display it"
            e return: 4 ]. 
    

    ifCurtailed: is a watchdog that reacts to abnormal stack behavior. For example, if we add a return statement in the receiver of the previous expression, the argument of the ifCurtailed: message is raised. Indeed the return statement is invalid since it is not defined in a method.

    [[ ^ 1 ]
            ifCurtailed: [ Transcript show: 'only shows curtailed'; cr. ]]
        on: Error do: [ :e |
            Transcript show: 'error 2'; cr. "does not display it"
            e return: 4 ]. 
    

    The following example shows that ensure: is executed systematically, even when no error is raised. Here the message should show ensure is displayed and 1 is returned as a value.

    [[ 1 ]
            ensure: [ Transcript show: 'should show ensure'; cr. 6 ]]
        on: Error do: [ :e |
            Transcript show: 'error'; cr. "does not display it"
            e return: 4 ]. 
    

    The following expression shows that when an error occurs the handler associated with the error is executed before the ensure: argument. Here the expression prints should show error first, then then should show ensure and it returns 4.

    [[ 1/0 ]
            ensure: [ Transcript show: 'then should show ensure'; cr. 6 ]]
        on: Error do: [ :e |
            Transcript show: 'should show error first'; cr.
            e return: 4 ]. 
    

    Finally the last expression shows that errors are executed one by one from the closest to the farthest from the error, then the ensure: argument. Here error1, then error2, and then then should show ensure are displayed.

    [[[ 1/0 ] ensure: [ Transcript show: 'then should show ensure'; cr. 6 ]]
        on: Error do: [ :e|
            Transcript show: 'error 1'; cr.
            e pass ]] on: Error do: [ :e |
                Transcript show: 'error 2'; cr. e return: 4 ].
    

    This page titled 12.11: Exceptions and ensure, ifCurtailed Interaction is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Alexandre Bergel, Damien Cassou, Stéphane Ducasse, Jannik Laval (Square Bracket Associates) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.