Skip to main content
Engineering LibreTexts

12.3: Handling Non-Local Returns

  • Page ID
    43731
  • \( \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}}\)

    The message ifCurtailed: is typically used for “cleaning” actions. It is similar to ensure:, but instead of ensuring that its argument block is evaluated even if the receiver terminates abnormally, ifCurtailed: does so only if the receiver fails or returns.

    In the following example, the receiver of ifCurtailed: performs an early return, so the following statement is never reached. In Smalltalk, this is referred to as a non-local return. Nevertheless the argument block will be executed.

    [^ 10] ifCurtailed: [Transcript show: 'We see this'].
    Transcript show: 'But not this'. 
    

    In the following example, we can see clearly that the argument to ifCurtailed: is evaluated only when the receiver terminates abnormally.

    [Error signal] ifCurtailed: [Transcript show: 'Abandoned'; cr].
    Transcript show: 'Proceeded'; cr.
    

    \(\bigstar\) Open a transcript and evaluate the code above in a workspace. When the pre-debugger windows open, first try selecting Proceed and then Abandon. Note that the argument to ifCurtailed: is evaluated only when the receiver terminates abnormally. What happens when you select Debug?

    Here are some examples of ifCurtailed: usage: the text of the Transcript show: describes the situation:

    [^ 10] ifCurtailed: [Transcript show: 'This is displayed'; cr]
    
    [10] ifCurtailed: [Transcript show: 'This is not displayed'; cr]
    
    [1 / 0] ifCurtailed: [Transcript show: 'This is displayed after selecting Abandon in the
        debugger'; cr]
    

    Although in Pharo ifCurtailed: and ensure: are implemented using a a marker primitive (described at the end of the chapter), in principle ifCurtailed: could be implemented using ensure: as follows:

    ifCurtailed: curtailBlock
        | result curtailed |
        curtailed := true.
        [ result := self value.
            curtailed := false ] ensure: [ curtailed ifTrue: [ curtailBlock value ] ].
        ^ result 
    

    In a similar fashion, ensure: could be implemented using ifCurtailed: as follows:

    ensure: ensureBlock
        | result |
        result := self ifCurtailed: ensureBlock.
        "If we reach this point, then the receiver has not been curtailed,
        so ensureBlock still needs to be evaluated"
        ensureBlock value.
        ^ result
    

    Both ensure: and ifCurtailed: are very useful for making sure that important “cleanup” code is executed, but are not by themselves sufficient for handling all exceptional situations. Now let’s look at a more general mechanism for handling exceptions.


    This page titled 12.3: Handling Non-Local Returns 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.