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

寵の児 提交于 2020-01-04 02:42:08

问题


I am trying to overload some built-in functions in Octave to perform a custom action prior to calling the built-in version of the overloaded function. In MATLAB (and supposedly Octave), I can do this using the builtin function.

The typical function definition would look something like this where I forward all inputs/outputs to/from the built-in after doing my custom action:

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

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

Now if I place this file (disp.m) on my path, any function which calls disp will execute my overloaded version which prints out extra information before calling the built-in disp function.

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

The issue I'm having is that this works for some built-ins but not all. For example, if I try to overload figure.

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

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

When I call this, builtin calls the the overloaded function again rather than the true built-in.

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

Interestingly, if I overload figure as a command-line function rather than saving it in figure.m it behaves exactly as I would expect.

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

Now one thing I noticed while debugging this was that Octave (obviously) issues a warning when you have a function with the same name as a built-in. If you look at the warnings, they are slightly different for the ones that function overloading works and does not work for:

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

The documentation does not seem to make any distinctions between core library functions and built-in functions and this behavior is not mentioned in the documentation for builtin.

Does anyone have any idea what causes this behavior and have any suggestions for how I can work around this issue?


回答1:


builtin only works for builtin functions. As you already understood, the problem is in the distinction between a builtin and a core library function.

Builtin function are built into the Octave interpreter itself.

Core library functions are functions that are distributed with Octave which includes, but is not limited to, the builtin functions. The other core library functions includes all functions written in the Octave language (m files) and dynamically linked functions (oct files). These other functions are not part of the Octave interpreter and only work because their directories are added to the Octave path.

Use which or exist to find out whether a function is builtin:

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

Of course, there is no promise that a function will remain a builtin or m file function between versions (although the reality is that this rarely changes).

Note that the logic is the same in Matlab but the set of builtin functions will be different.

Now the bit that I don't understand, is why does builtin behaves different at the Octave prompt. Independent of that, you can then just define your shadowed functions at .octaverc:

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


来源:https://stackoverflow.com/questions/37861252/inconsistent-behavior-of-builtin-when-overloading-built-in-functions-in-octave

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!