11.10.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:

  1. Globally visible functions
  2. Any function that the nested function’s parent can call
  3. Sibling functions (functions that have the same parents)
  4. 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

© 1996–2020 John W. Eaton
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://octave.org/doc/v6.3.0/Nested-Functions.html