11.10.4 嵌套函数

嵌套函数与子函数类似,都是只有主函数在文件外部可见。但嵌套函数还允许子函数访问其父函数中的局部变量。这种共享访问模拟了使用全局变量来共享信息——但这个全局变量对 Octave 的其他部分不可见。作为一种编程策略,以这种方式共享数据可能会导致代码难以维护。建议尽可能使用子函数来代替嵌套函数。

作为一个简单示例,考虑一个父函数 foo,它调用了一个嵌套的子函数 bar,并共享变量 x

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

  function bar ()
    x = 20;
  endfunction
endfunction

foo ()
 ⇒  20

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

现在考虑函数 foobar,它使用了变量 xyfoobar 调用嵌套函数 foo,该函数以 x 为参数并返回 yfoo 又调用了 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

需要注意的是,foobar 中的 xy 仍然保持为零,因为在 foo 中它们分别是返回值 和 参数。bat 中的 x 指的是 foo 中的 x

变量继承给 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 语句中,bar 中的 y 与其父函数 foo 中的 y 也是同一个变量。最好避免将 eval 与嵌套函数结合使用。

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

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

作为一个复杂示例,考虑一个父函数 ex_top,它有两个子函数 ex_aex_b。此外,ex_a 还有两个子函数 ex_aaex_ab。例如:

function ex_top ()
  ## 可以调用:ex_top、ex_a 和 ex_b
  ## 不能调用:ex_aa 和 ex_ab

  function ex_a ()
    ## 可以调用所有函数

    function ex_aa ()
      ## 可以调用所有函数
    endfunction

    function ex_ab ()
      ## 可以调用所有函数
    endfunction
  endfunction

  function ex_b ()
    ## 可以调用:ex_top、ex_a 和 ex_b
    ## 不能调用:ex_aa 和 ex_ab
  endfunction
endfunction

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

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