Anonymous function with a variable-length argument list - matlab

Can I create an anonymous function that accepts a variable number of arguments?
I have a struct array S with a certain field, say, bar, and I want to pass all the bar values to my anonymous function foo. Since the number of elements in struct S is unknown, foo must be able to accept a variable number of arguments.
The closest thing that I've been able to come up with is passing a cell array as the input argument list:
foo({arg1, arg2, arg3, ...})
and I'm invoking it with foo({S.bar}), but it looks very awkward.
Creating a special m-file just for that seems like an overkill. Any other ideas?

Using varargin as the argument of the anonymous function, you can pass a variable number of inputs.
For example:
foo = #(varargin)fprintf('you provided %i arguments\n',length(varargin))
Usage
s(1:4) = struct('bar',1);
foo(s.bar)
you provided 4 arguments

va_arg in matlab called varargin here is the content of the link
:
varargin is an input variable in a function definition statement that
allows the function to accept any number of input arguments.
function varlist(varargin)
fprintf('Number of arguments: %d\n',nargin);
celldisp(varargin)
varlist(ones(3),'some text',pi)
Number of arguments: 3
varargin{1} =
1 1 1
1 1 1
1 1 1
varargin{2} =
some text
varargin{3} =
3.1416
define anonymous function as 2 of 4 outputs of m file function

Related

How to pass Optional-Positional arguments to a function in matlab

I am trying to understand the usage of positional arguments in MATLAB and I was referring to this page.
Let's say I have a MATLAB function defined as follows:
function printPhoto(filename,varargin)
p = inputParser;
defaultFinish = 'glossy';
validFinishes = {'glossy','matte', 'colorful'};
checkFinish = #(x) any(validatestring(x,validFinishes));
defaultColor = 'RGB';
validColors = {'RGB','CMYK','colorful'};
checkColor = #(x) any(validatestring(x,validColors));
defaultWidth = 6;
defaultHeight = 4;
addRequired(p,'filename',#ischar);
addOptional(p,'finish',defaultFinish,checkFinish);
addOptional(p,'color',defaultColor,checkColor);
addParameter(p,'width',defaultWidth,#isnumeric);
addParameter(p,'height',defaultHeight,#isnumeric);
parse(p,filename,varargin{:});
end
When I call the above function as follows: printphoto('myFile.img', 'colorful'), is it possible to make this second argument to correspond to the second optional positional argument in the function definition i.e. color='colorful' and not finish='colorful'?
This is what you get when mixing optional-positional arguments and parameters. IMHO, you should use one or the other, but not both.
When you define an argument as positional, you're telling MATLAB that this input will always appear in that specific place, if it does appear. If you want to play around with the order of the inputs, that's exactly what a parameter-type argument is for.
Just think about it, the following syntaxes aren't that different:
printphoto('myFile.img','color','colorful')
printphoto('myFile.img', color='colorful' )
So I would suggest sticking with parameter-type arguments, but if you insist on having them positional, make sure that you assign a default value to the input if the user wants to "skip" it (by supplying some agreed-upon "null" value such as "" or []).

Matlab: Call function that has no outputs from an anonymous function

I'd like to call a certain function from within an anonymous function, as in
#(){fooBar(baz)}
Trouble is, fooBar has no outputs, which makes the anonymous function complain. Is there a way around this besides making the fooBar function return a dummy output?
The problem is in your anonymous function definition. By enclosing your function foobar(baz) between the characters {...}, you are programming a function which has to :
evaluate the expression foobar(baz)
Place the result of this expression into a cell
return the cell
Obviously in step (2) Matlab cannot place the result of the expression (1) in a cell because there is no output from (1).
So simply define your function without the curly braces:
myFunction = #() fooBar(baz)
and everything should work ok.
To demonstrate with an example, let's define the function fooBar by doing something which does not produce an output (change an axe limits for example):
fooBar = #(axlim) set(gca,'XLim',axlim)
I can now call fooBar([0 20]) and the current axes will directly have its axes limits set to [0 20]
If there is an axis span which I use often ([-5 5] for example), I could be tempted to define a new function which will always call fooBar with the same (often used) parameters:
fooBarPrefered = #() fooBar([-5 5])
Now every time I call fooBarPrefered(), my axes X limits are directly set to [-5 5].
To further prove the point, since calling fooBar([-5 5]) does not produce an output, Matlab will indeed complain if I define my function with curly braces:
fooBarPrefered = #() {fooBar([-5 5])} ;
>> fooBarPrefered()
One or more output arguments not assigned during call to "set".
Error in #(axlim)set(gca,'XLim',axlim)
Error in #(){fooBar([-5,5])}
But note that this is the same error than if you were trying to assign the output of fooBar to a variable directly in the workspace:
a = fooBar([0 20])
One or more output arguments not assigned during call to "set".
Error in #(axlim)set(gca,'XLim',axlim)
Bottom line: If a function does not have an output, do not try to redirect this output to a variable or an expression.

Correct use of tilde operator for input arguments

Function:
My MATLAB function has one output and several input arguments, most of which are optional, i.e.:
output=MyFunction(arg1,arg2,opt1,opt2,...,optN)
What I want to do:
I'd like to give only arg1, arg2 and the last optional input argument optN to the function. I used the tilde operator as follows:
output=MyFunction(str1,str2,~,~,...,true)
Undesired result:
That gives the following error message:
Error: Expression or statement is incorrect--possibly unbalanced (, {, or [.
The error points to the comma after the first tilde, but I don't know what to make of it to be honest.
Problem identification:
I use MATLAB 2013b, which supports the tilde operator.
According to MATLAB's documentation the above function call should work:
You can ignore any number of function inputs, in any position in the argument list. Separate consecutive tildes with a comma...
I guess there are a few workarounds, such as using '' or [] as inputs, but I'd really like to understand how to correctly use '~' because actually leaving inputs out allows me to use exist() when checking the input arguments of a function.
If you need any further info from me, please let me know.
Thank you very much!
The tilde is only for function declaration. Matlab's mlint recommends to replace unused arguments by ~. The result is a function declared like this function output = MyFunction(a, b, ~, c). This is a very bad practice.
Since you have a function where the parameters are optional, you must call the function with empty arguments output=MyFunction(str1,str2,[],[],...,true).
A better way to do it is to declare the function with the varargin argument and prepare your function for the different inputs:
function output = MyFunction(varargin)
if nargin == 1
% Do something for 1 input
elseif nargin == 2
% Do something for 3 inputs
elseif nargin == 3
% Do something for 3 inputs
else
error('incorrect number of input arguments')
end
It is even possible to declare your function as follows:
function output = MyFunction(arg1, arg2, varargin)
The declaration above will tell Matlab that you are expecting at least two parameters.
See the documentation of nargin here.
... and the documentation of varargin here
To have variable number of inputs, use varargin. Use it together with nargin.
Example:
function varlist2(X,Y,varargin)
fprintf('Total number of inputs = %d\n',nargin);
nVarargs = length(varargin);
fprintf('Inputs in varargin(%d):\n',nVarargs)
for k = 1:nVarargs
fprintf(' %d\n', varargin{k})
end

How to declare a function with an argument which is an array?

I need to declare a function that has 32 arguments, so it would be handy to put an unique argument: an array of 32 elements.
I don't find the syntax to do that, I've tried everythinh like:
function x=myfunction(str(32)) (etc...)
But without success.
Unlike other languages, MATLAB can accept matrices as a single argument; so you could just check that the input argument is a vector of length 32:
function x = myfunction(arg)
if length(arg) ~= 32
error('Must supply 32 arguments!');
end
%# your code here
end
If it's a variable number of arguments, check out varargin:
function x = myfunction(varargin)
But for 32 arguments, consider using an input structure:
function x = myfunction(argStruct)
if length(fieldnames(argStruct)) ~= 32
error('not enough arguments!');
end
Supply arguments in the structure, then pass the structure:
>> myArgs = struct();
>> myArgs.arg1 = 5;
>> myArgs.arg2 = 7;
>> %#(etc)
>> x = myfunction(myArgs);
Then in the function, you could either call argStruct.arg1, etc, directly; or unpack it into 32 different variables inside the function. I would give the fields descriptive names so you don't refer to them as arg1, etc inside your function. For that many input arguments, people using the function probably won't remember the order in which your function requires them to pass inputs to. Doing it with a struct lets users pass in arguments without needing to think about what order those inputs are defined.
To add to #strictlyrude27's awesome answer, it looks like you may misunderstand how function declarations work in Matlab. You wrote:
function x=myfunction(str(32))
However, you don't need to declare the type of input in matlab. Just give it a name, and then use it. So, the proper syntax for a declaration would be:
function x = myfunction(myInput)

Variable length MATLAB arguments read from variable

I have a function with variable arguments, declared in the standard way:
[] = foo ( varargin )
and I would like to call it from another function, but specify the arguments programmatically. My best attempt is something like the following:
% bar isn't populated like this, but this is how it ends up
bar = { 'var1' 'var2' 'var3' };
foo( bar );
However, bar is put into a 1x1 cell array, and not interpreted as a 1x3 cell array as I intended. I can't change foo, so is there a workaround?
If you have variables a, b, and c that you want to collect together somewhere and ultimately pass to a function as a series of inputs, you can do the following:
inArgs = {a b c}; % Put values in a cell array
foo(inArgs{:});
The syntax inArgs{:} extracts all the values from the cell array as a comma-separated list. The above is therefore equivalent to this:
foo(a,b,c);
If foo is written to accept a variable-length argument list, then the varargin variable will end up being a 1-by-3 cell array where each element stores a separate input argument. Basically, varargin will look exactly like the variable inArgs. If your call to foo didn't use the {:} operator:
foo(inArgs);
then the varargin variable would be a 1-by-1 cell array where the first element is itself the cell array inArgs. In other words, foo would have only 1 input (a 1-by-3 cell array).
The only way that I'm aware of is to use eval, however I don't have MATLAB here, so I can't check the syntax correctly.
If you coerce the bar into a string of the form "'var1', 'var2', 'var3'", you can do:
eval(["foo(", barString, ")"])
Hope that gets you going and sorry it isn't a comprehensive answer.