【问题标题】:Error when running simple script containing local function in Octave在 Octave 中运行包含本地函数的简单脚本时出错
【发布时间】:2021-04-01 14:14:19
【问题描述】:

我的文件 testtest.m 看起来像:

pluse(1, 2)
function retval = pluse(input1, input2)
retval = input1 + input2;
endfunction

然后我得到:

error: 'pluse' undefined near line 1 column 1
error: called from
    testtest at line 1 column 1

为什么会出现此错误?

【问题讨论】:

  • 你的文件应该有一个名字'pluse.m'
  • 感谢您的回答,但这样做会导致错误“在索引表达式中无效使用脚本 ~/Octave/pluse.m”。我真的不知道为什么这不起作用,因为我认为这是 Octave 的基本功能。 (我用的是 Octave 4.0.0,有问题吗?)
  • 这是基本的 matlab / octave 语法。 a) 函数通常在它们自己的文件中定义,b) 如果您想在现场定义一个函数,您需要先定义它才能使用它 c) 脚本文件可能不以 'function ' 声明,因为这是为函数文件保留的。请特别参阅octave.org/doc/interpreter/… 和octave.org/doc/interpreter/Function-Files.html#Function-Files 和octave.org/doc/interpreter/Script-Files.html#Script-Files。
  • 谢谢塔索斯。所以它与 MATLAB 不同,您可以在其中运行上面的代码。在 Octave 中,你需要这样做: [[[[ 1;函数 retval = pluse(input1, input2) retval = input1 + input2; endfunction pluse(1, 2) ]]]] ,我相信这有点尴尬。
  • 嗨,马丁。回复时请使用“标签”(例如@TasosPapastylianou),否则我不会收到通知(而线程的所有者,即您,会自动收到关于新 cmets 的通知,无论他们是否被标记)。我认为matlab没有什么不同;也许是最新的版本。旧版本甚至不支持像这样的“现场”函数定义,而 octave 多年来一直支持它们,所以也许 matlab 最近的实现是偶然的(或者故意弄乱 octave,哈哈)。不过我认为不应该,让我在工作中检查...

标签: octave


【解决方案1】:

要正确回答你的问题,我需要指出两点:

  1. 在 octave 和 matlab 中创建函数的规范方法是将其放在同名的专用文件中,并以 函数声明 开头。这样做的必然结果是,在启动时会检测到路径中以函数声明开头的任何文件,并将其作为可调用函数提供给用户。

  2. Octave 多年来一直支持“on-the-go”函数定义(实际上还支持后续将此类“on-the-go”函数“导出”到文件); matlab 最近才包含“on-the-go”功能(我相信是 2016b李>

Octave 的实现直接遵循语言规则。任何以不是“函数声明”的语句开头的文件都被视为脚本,即一系列独立语句。因此,脚本开头的 1 是无害的,它就像一个“非函数声明”语句一样简单,但实际上它可以是任何东西。然后,一个脚本可以根据需要拥有尽可能多的“on-the-go”函数定义。对于在“on-the-go”上下文中使用函数的语句,显然需要首先定义函数。这遵循以下基本原则:与函数相比,脚本有效地表示了一个简单的语句集合,这些语句按顺序运行而无需任何预处理,并且人们可以期望简单地将这些命令复制/粘贴到它们的终端并期望它们运行。

Matlab 最近的实现有效地打破了这个功能/范式。要明白我的意思,请将上面的代码复制粘贴到一个新的终端(或突出显示然后按 F9)并观察它的中断。脚本不再是可复制/粘贴的,但假定 matlab 会提前读取并加载任何函数定义first,然后then返回并尝试运行剩余的命令;换句话说,matlab 现在有点像对待它的功能一样对待脚本。请注意,matlab 仍然需要一个以非函数声明语句开头的脚本,因此该位实际上与需要以“1”开头的八度音程相同。唯一改变的是这种预先加载“on-the-go”函数的前瞻行为,我认为这在脚本上下文中不一定是一件好事。

我认为 Octave 的方法更有意义,尽管当(无意地)将脚本视为有效而不是脚本时,您使用 matlab 指出了方便。一开始可能不应该这样做。如果您需要前瞻功能和嵌套,您确实应该首先编写适当的函数并提供相关的范围上下文。

【讨论】:

  • 我已在 Octave 问题跟踪器 - savannah.gnu.org/bugs/index.php?56187 上发布了此功能请求,并将其作为 Matlab 功能请求提交给 MathWorks 支持。也许有一天我们会看到统一。
  • 我认为 Matlab 的方法至少是一致的:Matlab 的函数定义范式是声明性的而不是程序性的。与某些动态语言不同,函数不会在执行 function 语句时突然出现。它们总是在那里,因为它们存在于文件系统的某个地方,或者存在于 classdef 或函数定义文件中(或作为函数中的嵌套函数)。这很好,因为您不必担心“何时”定义它们。但是,您无法在其使用点附近定义脚本本地函数,这真是令人遗憾。
  • 这是另一个想法:也许 Matlab 要求局部函数位于脚本的末尾,以将它们与嵌套函数区分开来,嵌套函数是捕获对其包含函数内部变量的引用的闭包。也许也有可能支持脚本内的嵌套函数,它捕获脚本主体中的变量,而 Matlab 想要保留这种句法大小写。
【解决方案2】:

I had the same question/problem and some people gave the hints。但由于没有明确的示例,我将其发布在这里,以便其他人可以找到 Octave 和 MATLAB 的明确运行示例。

% works in Octave %%%
% sth. must be *before* a (local) function is declared
1; % or "2;" or "1+1;" or whatever

% local function must be declared *before* it is run in Octave
function retval = pluse(input1, input2)
  retval = input1 + input2;
end % or "endfunction"

% Now you can use the local function
pluse(1, 2)

还有 Octave 和 MATLAB 之间的不兼容,因为 MATLAB 示例不能在 Octave 中运行,反之亦然:

% works in MATLAB %%%
% You can use the local function
pluse(1, 2)

% local function must be declared at the end of file for MATLAB
function retval = pluse(input1, input2)
  retval = input1 + input2;
end

由于这种不兼容性,问题是是否真的应该使用本地函数。适用于 Octave 和 MATLAB 的解决方案是在另一个文件中使用“普通”函数...

【讨论】:

    猜你喜欢
    • 2019-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2023-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多