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