如何使用与 Matlab 脚本兼容的函数定义编写单个 Octave 脚本?

How to write a single Octave script with function definitions compatible with Matlab scripts?

如果我这样写:

clc
clear

close all
format long
fprintf( 1, 'Starting...\n' )

function results = do_thing()
    results = 1;
end

results = do_thing()

和运行它与Octave,它工作正常:

Starting...
results =  1

但是如果我尝试 运行 它与 Matlab 2017b,它会抛出这个错误:

Error: File: testfile.m Line: 13 Column: 1
Function definitions in a script must appear at the end of the file.
Move all statements after the "do_thing" function definition to before the first local function
definition.

那么,如果我修复错误如下:

clc
clear

close all
format long
fprintf( 1, 'Starting...\n' )

results = do_thing()

function results = do_thing()
    results = 1;
end

它在 Matlab 上正常工作:

Starting...

results =

     1

但是现在,它停止与 Octave:

一起工作
Starting...
error: 'do_thing' undefined near line 8 column 11
error: called from
    testfile at line 8 column 9

在这个问题上解释了这个问题:

如何在不必为函数创建单独的独占文件的情况下修复它 do_thing()

这个问题是否已在 Matlab2019a 的某些较新版本上得到解决?

Octave在脚本中对局部函数的实现与Matlab的不同。 Octave 要求脚本中的局部函数在使用前定义。但是Matlab要求脚本中的局部函数都定义在文件的end

因此,您可以在两个应用程序的脚本中使用本地函数,但您无法编写适用于两个应用程序的脚本。因此,如果您希望代码同时适用于 Matlab 和 Octave,则只需使用函数即可。

示例:

函数结束

disp('Hello world')
foo(42);

function foo(x)
  disp(x);
end

在 Matlab R2019a 中:

>> myscript
Hello world
    42

在 Octave 5.1.0 中:

octave:1> myscript
Hello world
error: 'foo' undefined near line 2 column 1
error: called from
    myscript at line 2 column 1

使用前的功能

disp('Hello world')

function foo(x)
  disp(x);
end

foo(42);

在 Matlab R2019a 中:

>> myscript
Error: File: myscript.m Line: 7 Column: 1
Function definitions in a script must appear at the end of the file.
Move all statements after the "foo" function definition to before the first local function definition. 

在 Octave 5.1.0 中:

octave:2> myscript
Hello world
 42

工作原理

请注意,从技术上讲,Octave 中的函数不是 "local functions",而是 "command-line functions"。他们没有定义脚本本地的函数,而是定义了在评估 function 语句时出现的全局函数。

答案在评论中,但为了清楚起见:

% in file `do_thing.m`
function results = do_thing()
    results = 1;
end

% in your script file
clc;   clear;   close all;   format long;
fprintf( 1, 'Starting...\n' );
results = do_thing();

伴随的解释性咆哮:

  • 定义函数的规范和最安全的方法是在它们自己的文件中定义它们,并使该文件在八度/matlab 的路径中可访问。
  • Octave 几乎永远支持 'dynamic' 函数定义(即在脚本或命令行的上下文中)。但是出于兼容性的考虑,由于matlab不支持这个,所以大多数人没有使用它,而是相当明智地依赖于规范的方式。
  • Matlab 最近也终于引入了动态函数定义,但已选择以破坏与八度音阶兼容性的方式显式实现它们,正如您上面描述的那样。 (咆哮:这可能是一个巧合和一个认真的设计决定,但我确实注意到它也恰好违反了先前关于嵌套函数的 matlab 约定,这些约定允许在其封闭范围内的任何地方定义)。
  • 从某种意义上说,一切都没有改变。 Matlab 与高级八度功能不兼容,现在它已经引入了自己的此功能实现,它仍然不兼容。这是因祸得福。为什么?因为,如果你想要相互兼容的代码,你应该依赖规范的形式和良好的编程实践,而不是在你的脚本中乱扔动态函数,无论如何你都应该这样做.