Skip to main content
Engineering LibreTexts

12.2: Ensuring Execution

  • Page ID
    43730
  • \( \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 ensure: message can be sent to a block to make sure that, even if the block fails (e.g., raises an exception) the argument block will still be executed:

    anyBlock ensure: ensuredBlock    "ensuredBlock will run even if anyBlock fails"
    

    Consider the following example, which creates an image file from a screenshot taken by the user:

    | writer |
    writer := GIFReadWriter on: (FileStream newFileNamed: 'Pharo.gif').
    [ writer nextPutImage: (Form fromUser) ]
        ensure: [ writer close ]
    

    This code ensures that the writer file handle will be closed, even if an error occurs in Form fromUser or while writing to the file.

    Here is how it works in more detail. The nextPutImage: method of the class GIFReadWriter converts a form (i.e., an instance of the class Form, representing a bitmap image) into a GIF image. This method writes into a stream which has been opened on a file. The nextPutImage: method does not close the stream it is writing to, therefore we should be sure to close the stream even if a problem arises while writing. This is achieved by sending the message ensure: to the block that does the writing. In case nextPutImage: fails, control will flow into the block passed to ensure:. If it does not fail, the ensured block will still be executed. So, in either case, we can be sure that writer is closed.

    Here is another use of ensure:, in class Cursor:

    Cursor»showWhile: aBlock
        "While evaluating the argument, aBlock,
        make the receiver be the cursor shape."
        | oldcursor |
        oldcursor := Sensor currentCursor.
        self show.
        ^aBlock ensure: [ oldcursor show ]
    

    The argument [ oldcursor show ] is evaluated whether or not aBlock signals an exception. Note that the result of ensure: is the value of the receiver, not that of the argument.

    [1]ensure:[0]    →    1    "not0"
    

    This page titled 12.2: Ensuring Execution 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.