当在八度中重载内置功能时,内置的行为不一致



我试图在八度的内置功能过载,以在调用内置版本的过载函数之前执行自定义操作。在MATLAB(据说是八度)中,我可以使用builtin函数进行此操作。

典型函数定义看起来像这样的东西,在执行自定义操作后,我将所有输入/输出转发到内置:

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的函数将执行我的超载版本,该版本在调用内置disp函数之前打印出额外的信息。

>> 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

现在,我在调试此事时注意到的一件事是,当您具有与内置的名称相同的功能时,八度(显然)发出警告。如果您查看警告,则它们的功能超载的警告略有不同,并且不适用于:

警告:函数./disp.m阴影一个内置的函数< - works
警告:函数./figure.m阴影核心库函数< - 不起作用

文档似乎没有在核心库函数和内置功能之间有任何区别,并且builtin的文档中未提及此行为。

有人知道是什么原因导致这种行为,并且对我如何解决这个问题有任何建议?

builtin仅适用于内置功能。正如您已经了解的那样,问题在于内置和核心库函数之间的区别。

内置函数内置在八度解释器本身中。

核心库函数是用八度分布的函数,其中包括但不限于内置功能。其他核心库功能包括用八度语言(M文件)编写的所有功能和动态链接的功能(OCT文件)。这些其他功能不是八度解释器的一部分,仅是因为它们的目录被添加到八度路径中。

使用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在八度提示下行为不同。独立于此,您可以在.octaverc上定义阴影功能:

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

最新更新