Understanding nargout(@plot) and detecting "varargout-only" functions

I am trying to understand why nargout(@plot) returns 1.
>> nargout(@plot)
ans =
1
My ulterior motive is to be able to detect whether a function has varargout as its only only output argument in its function signature (and whatever the equivalent is for built-in functions).
According to the nargout documentation, a function handle to a function with only a variable number of output arguments,
function varargout=test(varargin)
will produce an nargout result of -1. This is corroborated by the following test and so seems like a good way to achieve what I am after.
>> nargout(@test)
ans =
-1
But surely plot() is in the same category. The 'ans' variable is unaffected when plot() is called with no output arguments.
>> ans=pi
ans =
3.1416
>> plot(1:5); ans
ans =
3.1416
Can anyone make sense of this behavior? If this is intended, then how can one auto-detect whether a function has a variable number of output arguments?

Answers (2)

plot is a built-in command. It can have 1 output argument, such that nargout(@plot) is expected to reply 1.
But surely plot() is in the same category
Why are you sure? A built-in or Mex function is allowed to reply one output, but can leave the output undefined also. Then ans is not created or overwritten.
// file: myAnsTest
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
if (mxGetScalar(prhs[0]) == 1.0) {
plhs[0] = mxCreateDoubleScalar(3.14);
}
}
Now compile and call it:
ans = -1
myAnsTest(0)
ans
myAnsTest(1)
ans
I assume, that an auto-detection of the number of outputs is meta-programming. Are you really sure that this is useful for your work?

6 Comments

So you are saying it is an issue of mfiles versus builtins? But if so, then why the following behavior? Arrayfun is also a builtin which "can have 1 output argument".
>> nargout(@arrayfun)
ans =
-1
Also, if nargout(fun) was not meant to apply to builtins, why is rand (a builtin) given as an example in the nargout documentation? It would be pretty useless if nargout required us to distinguish between mfiles and builtins.
I guess - of course a reverse engineering is not allowed by the license agreement - that some built-in files are P-files, such that the original code can contain a varargout and in consequence nargout can retrieve details, while this is not possible (in a documented way) for Mex files.
A user has posted this error message:
??? Error using ==> nargout
foo does not know how to answer nargin/nargout.
See https://www.mathworks.com/matlabcentral/answers/24953-how-to-make-a-mex-answer-nargin-nargout. This sounds, like there is a way, in which a function can answer a request to nargin/nargout. But I do not know, how to ask or implement this.
I am not saying, that there is this difference, but this is guessing. I'm convinced that meta-programming like the automatic detection of the number of arguments make the life as programmer much harder and avoid it completely. I have enough problems to solve with non-meta-methods, such that I move the meta-problems to the bottom of my pipeline. But maybe you have a really good reason to think, that this is useful. I suggest to think twice.
function vargout=test(varargin)
if nargin==1
vargout{1}=10;
vargout{2}=20;
else
varout{1}=1;
varout{2}=2;
varout{3}=3;
varout{4}=4;
end
end
Maybe this is more usefull for you. Depends on number of input arguments you could have more choice of outputs arguments. Some kind of function overloading.
>>x=nargout(@test)
returns
x=-1
as Jan already write the number of output argument would be defined in runtime.
function [a c b d]=test(varargin)
if nargin=1
a=10;
b=20;
else
a=1;
b=2;
c=3;
d=4;
end
end
but in this case independent of your input numer of arguments, the answer of nargout(@test) would returns 4.
@Jan,
I'm convinced that meta-programming like the automatic detection of the number of arguments make the life as programmer much harder and avoid it completely.
So you never use nargin or nargout??
@Sayyed,
Sorry, I do not understand your comment.
I tend to use narginchk quite often and nargin on a function handle that I am passing in to use as a callback and I am going to be passing the arguments to it so I like to assert on nargin just for extra security, though I tend to only do this for functions that should have fixed input arguments rather than varargin. I'm not sure I've ever found much use for checking nargout, although I suppose the same reasons as checking nargin maybe hold.
@Matt J: There are 2 cases:
  1. Using nargin and nargout inside a function: Here the function examines how it was called and the results concern the current state of Matlab. This is not an analysis of code. Not "meta".
  2. nargout(@fun) checks the properties of other functions. The source code it examined to do this: "meta".
I never use the 2nd method. Most of all not in productive code. Yes, I admit, I've written some unproductive code also: E.g. a tool which checks offline if all M files with constructs like:
try
catch ME
disp(ME.message)
end
use a correctly spelled "message" and not "meesage". This typo can be found by exhaustive checks of all exceptions in the unit-tests, but it is not trivial to prove, that the tests are exhaustive. Therefore I use a tool to check these symbols automatically. But as said, this does not run during the productive work, but offline during the unit-testing.

Sign in to comment.

My ulterior motive is to be able to detect whether a function has varargout as its only only output argument in its function signature (and whatever the equivalent is for built-in functions).
Why? How are you planning to use this information?
Re: @plot.
Yes, plot does not assign a value to ans when it is called with 0 input arguments. I'm not certain exactly why that decision was made (it was made a Long Time ago, before I joined MathWorks) but I suspect it was to avoid confusion. If it did assign to ans when called with 0 inputs, it would have been (relatively) common to see something like "ans = 123.456789" (a Handle Graphics handle under the original Handle Graphics system) displayed when you ran your code. I think the assumption was that if you called plot with an output you cared about manipulating the graphics object after creation, but if you didn't you didn't care about the handle at all so why show it (and if you later on did decide you needed the handle, findobj exists.)
That does not mean it uses varargout or the equivalent for built-in functions.

1 Comment

That does not mean it uses varargout or the equivalent for built-in functions.
But then what does it mean? And how is nargout(fun) to be interpreted for built-in functions?
Why? How are you planning to use this information?
The motivation is a bit moot right now. In earlier versions of MATLAB, I was seeing problems with wrapper constructs like the following,
function varargout=wrapper(funchandle, varargin)
%Some code
[varargout{1:nargout}]=funchandle(varargin{:});
%More code
end
The problem was that, when nargout=0, a wrapper like the above would always return zero output arguments, which makes a lot of sense. But sometimes (depending on funchandle) you do want to return an output even when one is not requested. In fact, most stock Matlab functions behave this way, e.g.,
>> sind(90) %no outputs requested
ans =
1
I've only now noticed that this is no longer a problem in recent MATLAB, but in the days when it was, a check like what I've been asking about would have been the solution.

Sign in to comment.

Asked:

on 23 Jul 2018

Commented:

Jan
on 23 Jul 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!