octave: Nested Functions

 
 11.9.4 Nested Functions
 -----------------------
 
 Nested functions are similar to subfunctions in that only the main
 function is visible outside the file.  However, they also allow for
 child functions to access the local variables in their parent function.
 This shared access mimics using a global variable to share information —
 but a global variable which is not visible to the rest of Octave.  As a
 programming strategy, sharing data this way can create code which is
 difficult to maintain.  It is recommended to use subfunctions in place
 of nested functions when possible.
 
    As a simple example, consider a parent function ‘foo’, that calls a
 nested child function ‘bar’, with a shared variable X.
 
      function y = foo ()
        x = 10;
        bar ();
        y = x;
 
        function bar ()
          x = 20;
        endfunction
      endfunction
 
      foo ()
       ⇒ 20
 
 Notice that there is no special syntax for sharing X.  This can lead to
 problems with accidental variable sharing between a parent function and
 its child.  While normally variables are inherited, child function
 parameters and return values are local to the child function.
 
    Now consider the function ‘foobar’ that uses variables X and Y.
 ‘foobar’ calls a nested function ‘foo’ which takes X as a parameter and
 returns Y.  ‘foo’ then calls ‘bat’ which does some computation.
 
      function z = foobar ()
        x = 0;
        y = 0;
        z = foo (5);
        z += x + y;
 
        function y = foo (x)
          y = x + bat ();
 
          function z = bat ()
            z = x;
          endfunction
        endfunction
      endfunction
 
      foobar ()
          ⇒ 10
 
 It is important to note that the X and Y in ‘foobar’ remain zero, as in
 ‘foo’ they are a return value and parameter respectively.  The X in
 ‘bat’ refers to the X in ‘foo’.
 
    Variable inheritance leads to a problem for ‘eval’ and scripts.  If a
 new variable is created in a parent function, it is not clear what
 should happen in nested child functions.  For example, consider a parent
 function ‘foo’ with a nested child function ‘bar’:
 
      function y = foo (to_eval)
        bar ();
        eval (to_eval);
 
        function bar ()
          eval ("x = 100;");
          eval ("y = x;");
        endfunction
      endfunction
 
      foo ("x = 5;")
          ⇒ error: can not add variable "x" to a static workspace
 
      foo ("y = 10;")
          ⇒ 10
 
      foo ("")
          ⇒ 100
 
 The parent function ‘foo’ is unable to create a new variable X, but the
 child function ‘bar’ was successful.  Furthermore, even in an ‘eval’
 statement Y in ‘bar’ is the same Y as in its parent function ‘foo’.  The
 use of ‘eval’ in conjunction with nested functions is best avoided.
 
    As with subfunctions, only the first nested function in a file may be
 called from the outside.  Inside a function the rules are more
 complicated.  In general a nested function may call:
 
   0. Globally visible functions
 
   1. Any function that the nested function’s parent can call
 
   2. Sibling functions (functions that have the same parents)
 
   3. Direct children
 
    As a complex example consider a parent function ‘ex_top’ with two
 child functions, ‘ex_a’ and ‘ex_b’.  In addition, ‘ex_a’ has two more
 child functions, ‘ex_aa’ and ‘ex_ab’.  For example:
 
      function ex_top ()
        ## Can call: ex_top, ex_a, and ex_b
        ## Can NOT call: ex_aa and ex_ab
 
        function ex_a ()
          ## Can call everything
 
          function ex_aa ()
            ## Can call everything
          endfunction
 
          function ex_ab ()
            ## Can call everything
          endfunction
        endfunction
 
        function ex_b ()
          ## Can call: ex_top, ex_a, and ex_b
          ## Can NOT call: ex_aa and ex_ab
        endfunction
      endfunction