在 Octave 中重载内置函数时内置函数的不一致行为

Inconsistent behavior of builtin when overloading built-in functions in Octave

我正在尝试重载 Octave 中的一些内置函数,以便在调用重载函数的内置版本之前执行自定义操作。在 MATLAB(应该是 Octave)中,我可以使用 builtin 函数来做到这一点。

典型的函数定义看起来像这样,我在执行自定义操作后转发所有 inputs/outputs to/from 内置函数:

function varargout = disp(varargin)
    % Do a custom thing
    fprintf('Calling overloaded disp!\n')

    % Now call the builtin
    [varargout{1:nargout}] = builtin('disp', varargin{:});
end

现在,如果我将这个文件 (disp.m) 放在我的路径上,任何调用 disp 的函数都会执行我的重载版本,它会在调用内置 [=17] 之前打印出额外的信息=]函数。

>> disp('hello world')
Calling overloaded disp!
hello world

我遇到的问题是这适用于 一些 内置插件,但不是全部。例如,如果我尝试重载 figure.

function varargout = figure(varargin)
    disp('Creating a figure!')

    [varargout{1:nargout}] = builtin('figure', varargin{:});
end

当我调用它时,builtin 再次调用 重载函数 而不是真正的内置函数。

>> figure()
Creating a figure!
Creating a figure!
Creating a figure!
...
error: max_recursion_depth exceeded

有趣的是,如果我将 figure 作为命令行函数重载而不是将其保存在 figure.m 中,它的行为完全符合我的预期。

> function varargout = figure(varargin), disp('here'), [varargout{1:nargout}] = builtin('figure', varargin{:}), endfunction
> figure()
here

现在我在调试时注意到的一件事是当你有一个与内置函数同名的函数时,Octave(显然)会发出警告。如果您查看警告,它们对于函数重载有效和无效的警告略有不同:

warning: function ./disp.m shadows a built-in function <-- WORKS
warning: function ./figure.m shadows a core library function <-- DOES NOT WORK

文档似乎没有对核心库函数和内置函数进行任何区分,builtin 的文档中也没有提到这种行为。

有没有人知道导致此行为的原因并对我如何解决此问题有任何建议?

builtin 仅适用于内置函数。如您所知,问题在于内置函数和核心库函数之间的区别。

内置函数内置于 Octave 解释器本身。

核心库函数是随Octave一起分发的函数,包括但不限于内置函数。其他核心库函数包括所有用 Octave 语言编写的函数(m 文件)和动态链接函数(oct 文件)。这些其他函数不是 Octave 解释器的一部分,只是因为它们的目录被添加到 Octave 路径才起作用。

使用whichexist判断一个函数是否是内置的:

octave> which disp
'disp' is a built-in function from the file libinterp/corefcn/pr-output.cc
octave> which figure
'figure' is a function from the file /home/carandraug/.local/share/octave/4.1.0+/m/plot/util/figure.m
octave> which audioread 
'audioread' is a function from the file /home/carandraug/.local/lib/octave/4.1.0+/oct/x86_64-pc-linux-gnu/audioread.oct

octave> exist ("disp", "builtin")
ans =  5
octave> exist ("figure", "builtin")
ans = 0
octave> exist ("audioread", "builtin")
ans = 0

当然,我们无法保证某个函数在不同版本之间仍将是内置函数或 m 文件函数(尽管事实是这很少改变)。

请注意,Matlab 中的逻辑相同,但内置函数集会有所不同。

现在我不明白的一点是,为什么 builtin 在 Octave 提示符下表现不同。独立于此,您可以在 .octaverc:

处定义阴影函数
$ tail -n 5 ~/.octaverc 
function varargout = figure (varargin)
  mlock ();
  disp ("here");
  [varargout{1:nargout}] = builtin ("figure", varargin{:});
endfunction
$ octave
octave> figure
here