nargout with class method handles

22 Ansichten (letzte 30 Tage)
Markus Leuthold
Markus Leuthold am 22 Apr. 2015
Kommentiert: Walter Roberson vor etwa 13 Stunden
Assume you have the following class
classdef MyClass
methods
function fcn(~)
end
end
end
The following call of nargout
c=MyClass;
nargout(@c.fcn)
always returns -1, no matter how many output arguments the function has. Why is that?
I'm aware this already has been discussed here, but the proposed workaround
nargout('MyClass>MyClass.fcn')
is not suitable if you only know the function handle. The provided answer is already 5 years old, is there an update on this shortcoming?

Antworten (1)

Guillaume
Guillaume am 22 Apr. 2015
With no guarantee that it works in all cases, this may be a workaround (not a pretty one):
function nout = nargout_for_class_fhandle(fhandle)
finfo = functions(fhandle);
fwspace = finfo.workspace{1};
wspacefields = fieldnames(fwspace);
mc = metaclass(fwspace.(wspacefields{1}));
searchnames = cellfun(@(name) sprintf('%s//.%s', wspacefields{1}, name), {mc.MethodList.Name}, 'UniformOutput', false);
midx = find(regexp(finfo.function, searchnames, 'once'));
mm = mc.MethodList(midx);
nout = numel(mm.OutputNames);
end
I've not put any error checking in there and because it attempts to find the method name in the body of the anonymous function code it could be defeated.
  4 Kommentare
Nick
Nick vor etwa 4 Stunden
Thank you, Walter, for pointing this case! You're of course right.
Is there a way to directly return ('delegate') vargout from nested function without assigning that to a named return argument of the calling function?
My case is following: I have a sort of API gateway, which handle calling the methods of different implementations. Each of those methods might have same amount of outputs across different implementation classes, but I don't have a table how many outputs are registered for each of the APIs methods. It looks as following:
function [varargout] = genericFcn(varargin, options)
...
api = ...; % I need to find the implementation instance
methodName = ...; % The method, I'll be calling from the instance
if staticMethod
% I was using nargout for case of static methods - which works well,
% but obviously won't work, if the nargout will have a negative result:
f = str2func([class(api) '.' methodName]);
% For this assignment, I need to know how many return aguments will
% be, and for static methods it works well, unless there is
% varargout used there (which is not the case in my classes)
[varargout{1:nargout(f)}] = f(allArguments{:});
else
% whatever I can use to collect returned arguments - e.g.
% downcounting from 10 (I know that no methods will return more
% than 10 return arguments)
% Here nargout(f) always returns "Function <methodName> does not
% exist", even if the right part "f(api, allArguments{:})" could be
% executed well.
% My attempts with
% nargout('api.remote.XX>api.remote.XX.methodName') bring the same
% error - "Function does not exist".
end
end
How to use nargout in this case, if I need to return whatever output arguments will be, including the case, when they're defined as optional?
Thank you!
Walter Roberson
Walter Roberson vor etwa 13 Stunden
Consider the case of size .
A = [3 1 4 1];
[S{1:1e7}] = size(A);
S{end}
ans = 1
If there is a limit to the number of output arguements (aside from the available memory and the maximum array size of 2^48 bytes), the limit must be very large.
Consider that using size() with at least two output arguments returns individual outputs, with the first output being the size of the first dimension, then all of the rest of the outputs except the last being the size of the intermediate dimensions, and with the last output argument being the product of all remaining dimensions.
But size() with a single output argument returns a vector of the declared dimensions of the variable.
Any attempt to guess the desired number of outputs by examining the function signature of size() is doomed to failure. If the guess is exactly 1 then you will get the vector of sizes, which might be the wrong thing in context. If the guess is 2 or more then you will get individual sizes, which might be the wrong thing in context.
Any time the function has a variable number of outputs, you might be guessing wrong if you examine the function signature.
Now consider a function such as legend(). legend() is currently documented as returning either zero or one outputs. However, there is undocumented backwards compatibility, and in a wide range of MATLAB versions, the very way that legend() operates depends on the number of outputs: 2 or more outputs used to use entirely different data structures to represent the legend entries.
There are other functions that take different computation paths depending on the number of outputs.
There are functions where the nominal output arguements differs depending on the number of outputs. For example you have R = qr(...) but you have [Q, R] = qr(...) -- the meaning of the first output is different depending on the number of outputs you specify. But nargout(@qr) returns a solid 3, not -1 (indicating 1 output followed by variable outputs).
You need to do one of the following:
  • build a table of the expected number of outputs for each function taking into account that in some calling sequences the expected number might be different
  • rely on nargout() of the genericFcn() call to indicate the number of outputs expected from the API call
  • pass the expected number of outputs as part of the call to genericFcn()

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Argument Definitions finden Sie in Help Center und File Exchange

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by