Skip to main content
Engineering LibreTexts

13.3: Variables Can Outlive Their Defining Method

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

    Non-block local variables referred to by a block continue to be accessible and shared with other expressions even if the method execution terminated. We say that variables outlive the method execution that defined them. Let’s look at some examples.

    Method-Block Sharing. We start with a simple example showing that a variable is shared between a method and a block (as in the previous experiments in fact). Define the following method foo which defines a temporary variable a.

    Bexp>>foo
        |a|
        [ a := 0 ] value.
        ^a
    
    Bexp new foo
        → 0
    

    When we execute Bexp new foo, we get 0 and not nil. What you see here is that the value is shared between the method body and the block. Inside the method body we can access the variable whose value was set by the block evaluation. Both the method and block bodies access the same temporary variable a.

    Let’s make it slightly more complicated. Define the method twoBlockArray as follows:

    Bexp>>twoBlockArray
        |a|
        a := 0.
        ^ {[ a := 2] . [a]}
    

    The method twoBlockArray defines a temporary variable a. It sets the value of a to zero and returns an array whose first element is a block setting the value of a to 2 and second element is a block just returning the value of the temporary variable a.

    Now we store the array returned by twoBlockArray and evaluate the blocks stored in the array. This is what the following code snippet is doing.

    | res |
    res := Bexp new twoBlockArray.
    res second value.    → 0
    res first value.
    res second value.    → 2
    

    You can also define the code as follows and open a transcript to see the results.

    | res |
    res := Bexp new twoBlockArray.
    res second value traceCr.
    res first value.
    res second value traceCr.
    

    Let us step back and look at an important point. In the previous code snippet when the expressions res second value and res first value are executed, the method twoBlockArray has already finished its execution - as such it is not on the execution stack anymore. Still the temporary variable a can be accessed and set to a new value. This experiment shows that the variables referred to by a block may live longer than the method which created the block that refers to them. We say that the variables outlive the execution of their defining method.

    You can see from this example that while temporary variables are somehow stored in an activation context, the implementation is a bit more subtle than that. The block implementation needs to keep referenced variables in a structure that is not in the execution stack but lives on the heap. The compiler performs some analysis and when it detects that a variable may outlive its creation context, it allocates the variables in a structure that is not allocated on the execution stack.


    This page titled 13.3: Variables Can Outlive Their Defining Method 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.