简体   繁体   中英

Matlab anonymous function with variable number of input and output arguments

I am trying to write an anonymous function to generate strings for plotting several variables in multiple figures.

I would like to find an approach that will allow me to implement something like

vtext=@(v) horzcat('X1,',v,'1,''.'',X2,',v,'2,''.'',X3,',v,'3,''.''');
makevtext=@(varargin) vtext(varargin{:});
[atext,btext,ctext]=makevtext('a','b','c');

to produce the strings:

atext = X1,a1,'.',X2,a2,'.',X3,a3,'.'
btext = X1,b1,'.',X2,b2,'.',X3,b3,'.' 
ctext = X1,c1,'.',X2,c2,'.',X3,c3,'.' 

which I will be using to generate multiple plots of a, b and c later on. I'm using an anonymous function because I'd like to be able to easily change which variables I use this on as I explore my data (eg, if I instead want to see figures for a, d and e, or for vtext to also include X4 and a/d/e4, etc.), but without having to go through my code and change the arguments of something like 20 plots every time I do this. For context, 1,2,3,4,... are different kinds of distributions (Pareto, exponential, etc.), while a,b,c,d,e,... are histogram counts, PDF, CDF, exceedance, and a number of other derivative functions.

Right now, the above code works if I run atext=makevtext('a') , but [atext,btext]=makevtext('a','b') gives me a "Too many input arguments" error. If I replace line 2 above with (just deleting the "{:}"):

makevtext=@(varargin) vtext(varargin);

then [atext,btext]=makevtext('a','b') gives me a "Too many output arguments" error, but I can also get (incorrectly):

[atext] = makevtext('a')
     atext = 
       1x5 cell array
        'X1,'    'a'    '1,'.',X2,'    'a'    '2,'.''

[abtext] = makevtext('a','b')
     atext = 
       1x7 cell array
        'X1,'    'a'    'b'    '1,'.',X2,'    'a'    'b'    '2,'.''

I know it's supposed to be possible to use both varargin and have multiple outputs in anonymous functions, but can't find any examples using both. Is there actually any way to do this, or do I need to use a different approach entirely?

The makevtext function as in the question doesn't add anything to vtext , it simply returns its output. We need to do a little bit more work to get multiple outputs. And to use the multiple inputs to generate different strings.

First of all, cellfun can be used to apply vtext to each element in varargin :

cellfun(vtext,varargin,'UniformOutput',false)

This returns a new cell array, with each element a string created by vtext . Now we need to split it into multiple outputs. Indexing a cell array like so: A{:} outputs all elements as a comma-separated list. deal turns this into multiple outputs (see https://blogs.mathworks.com/loren/2007/01/31/multiple-outputs/ ). Thus we get this code:

>> vtext=@(v) horzcat('X1,',v,'1,''.'',X2,',v,'2,''.'',X3,',v,'3,''.''');
>> makevtext=@(varargin) deal(cellfun(vtext,varargin,'UniformOutput',false){:});
>> [atext,btext,ctext]=makevtext('a','b','c')
atext = X1,a1,'.',X2,a2,'.',X3,a3,'.'
btext = X1,b1,'.',X2,b2,'.',X3,b3,'.'
ctext = X1,c1,'.',X2,c2,'.',X3,c3,'.'

This works in Octave, but it probably doesn't work in MATLAB because MATLAB doesn't let you index on the return of a function directly. It probably needs a more verbose version:

A{:} is equivalent to subsref(A,substruct('{}',{':'})) . Thus we can do:

makevtext=@(varargin) deal(subsref(cellfun(vtext,varargin,'UniformOutput',false),substruct('{}',{':'})));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM