11.10.4嵌套函数

嵌套函数与子函数的相似之处在于,只有主函数在文件外部可见。然而,它们也允许子函数访问其父函数中的局部变量。这种共享访问模仿了一个全局变量来共享信息,但全局变量对Octave的其他部分不可见。作为一种编程策略,以这种方式共享数据可能会创建难以维护的代码。建议尽可能使用所有子函数来代替嵌套函数。

作为一个简单的例子,考虑一个父函数foo,调用nestedchild函数bar,具有共享变量x.

function y = foo ()
  x = 10;
  bar ();
  y = x;

  function bar ()
    x = 20;
  endfunction
endfunction

foo ()
 ⇒ 20

请注意,共享没有特殊语法x。这可能导致父函数与其子函数之间意外共享变量的问题。虽然通常变量是继承的,但子函数的参数和返回值是子函数的局部值。

现在考虑函数foobar使用变量xy. foobar调用嵌套函数foo需要x作为参数并返回y. foo然后调用bat它进行一些计算。

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

需要注意的是xy在里面foobarremainzero,如foo它们分别是返回值和参数。这里的x在里面bat指的是x在里面foo.

变量继承导致的问题eval和脚本。如果在父函数中创建了新的变量,则不清楚嵌套的子函数中应该发生什么。例如,考虑一个父函数foo具有嵌套的子函数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

父函数foo无法创建新变量x,但是子函数bar是成功的。此外,即使在eval语句y在里面bar是一样的y如同在其父函数中一样foo。的使用eval最好避免与嵌套函数结合使用。

与子函数一样,只能从外部调用文件中的第一个嵌套函数。在函数内部,规则更为复数。一般来说,嵌套函数可以调用:

  1. 全局可见函数
  2. 嵌套函数的父级可以调用的任何函数
  3. 兄弟函数(具有相同父级的函数)
  4. 直接子级对象

作为一个复数的例子,考虑一个父函数ex_top具有两个子函数,ex_aex_b此外ex_a具有另外两个子函数,ex_aaex_ab例如

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

版权所有 © 2024-2025 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-2