Spec-Zone.ru › Octave 5

11.9.4 Вложенные функции

Вложенные функции похожи на подфункции тем, что только основная функция видна снаружи файла. Однако они также позволяют дочерним функциям обращаться к локальным переменным в их родительской функции. Этот общий доступ имитирует использование глобальной переменной для обмена информацией — но глобальной переменной, которая не видна остальной части Octave. В качестве стратегии программирования такое совместное использование данных может привести к сложностям в обслуживании кода. Рекомендуется использовать подфункции вместо вложенных функций, когда это возможно.

В качестве простого примера рассмотрим родительскую функцию foo, которая вызывает вложенную дочернюю функцию bar, с общей переменной x.

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

  function bar ()
    x = 20;
  endfunction
endfunction

foo ()
 ⇒ 20

Обратите внимание, что нет специальной синтаксической конструкции для обмена x. Это может привести к проблемам с непреднамеренным обменом переменными между родительской функцией и ее дочерней функцией. Хотя обычно переменные наследуются, параметры и возвращаемые значения дочерней функции локальны для дочерней функции.

Теперь рассмотрим функцию foobar, которая использует переменные x и y. 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

Важно отметить, что x и y в foobar остаются нулевыми, как в 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_a и ex_b. Кроме того, ex_a имеет еще две дочерние функции, ex_aa и ex_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

© 1996–2022 The Octave Project Developers
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://docs.octave.org/v5.2.0/Nested-Functions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API