嵌套函数在 octave/matlab 中看不到局部变量

Nested function does not see local variable in octave/matlab

我正在尝试在我的八度环境中使用名为 optprop 的 matlab 模块。看来代码有一些兼容性问题。特别是,当我尝试调用

xyz_image = rgb2xyz(rgb_image)

我收到以下错误:

error: 'cwf' undefined near line 1809 column 15
error: called from
    astm>getcwf at line 1809 column 4
    astm at line 1843 column 5
    makecwf>tryastm at line 74 column 5
    makecwf at line 59 column 9
    wpt at line 33 column 6
    i_xyz2xyz at line 28 column 6
    i_rgb2xyz at line 54 column 5
    optproc at line 315 column 7
    rgb2xyz at line 49 column 33
    rgb2xyz_norm2 at line 10 column 12

导致错误的代码在astm.m文件中。此文件定义函数:

function z=astm(op,varargin)
    persistent cwf lam
    %cwf initialization

    %nested function
    function z=getcwf(name, varargin)
        %...
        z=cwf;  %here cwf is undefined
        %...

    %actual nested function call
    z=getcwf(varargin{:});
    %...

在我看来这里一切都很好。嵌套函数应参见 cwf。即使我使用 octave,它也应该支持一切,因为 optprop 包上次更新是在 2007 年。我还尝试了嵌套函数,下面的代码工作得很好:

function nested_function_test()
    disp('inside outer function');
    local_variable = 'local string content';

    function nested_function()
        disp('inside nested function');
        disp(local_variable);
    end

    disp('after nested function declaration');
    nested_function();
end

我看不出这些代码块有什么区别。为什么 cwf 未定义?

更新:

以防万一。当前对我有用的解决方法:

function z=getcwf(name, varargin)
    cwf = varargin{end - 1};
    lam = varargin{end};
    %...


varargin{end + 1} = cwf;
varargin{end + 1} = lam;
z=getcwf(varargin{:});

这似乎是 Octave 中的一个明确错误。在您的 MWE 中,如果您使 local_variable 持久化,则将重现错误行为。即

function nested_function_test()
  disp('inside outer function');
  persistent local_variable;  % <-- change here, make local_variable persistent
  local_variable = 'local string content';

  function nested_function()
    disp('inside nested function');
    disp(local_variable);  % <-- local_variable no longer visible
  end

  disp('after nested function declaration');
  nested_function();
end

以上将在 matlab 中运行,但在 Octave 中失败。

特别是,在 matlab 中,在嵌套函数内的调试会话期间,如果您键入 whos,您将看到两堆变量,一个(空)工作区位于嵌套函数的本地,另一个对应到外部函数,嵌套的内部函数可以访问,包含持久变量。

在 Octave 中,在嵌套函数中键入 whos 只是 returns 一个空的本地工作区,仅此而已。 (如果你删除 persistent 行,你会看到 octave 似乎只是 'import' 将外部局部变量放入本地工作区,而不是同时访问内部和外部,所以看起来 octave对如何创建嵌套函数有不同的方法)。

我鼓励您将此作为正式错误提交到 octave bug tracker1 中。似乎开发人员可能将持久变量视为一种特殊情况,而忘记在他们的嵌套函数的特定实现中考虑这种行为。大概是'import'这一步在特定的地方查看变量,而持久变量存储在别处而遗漏了?


1:啊,看来这个bug已经被报告和确认了,但还没有修复:https://savannah.gnu.org/bugs/index.php?42126