How to pass Optional-Positional arguments to a function in matlab - 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 []).

Related

Can an anonymous function in MATLAB have more than one line? [duplicate]

I'd like to do something like this:
>> foo = #() functionCall1() functionCall2()
So that when I said:
>> foo()
It would execute functionCall1() and then execute functionCall2(). (I feel that I need something like the C , operator)
EDIT:
functionCall1 and functionCall2 are not necessarily functions that return values.
Trying to do everything via the command line without saving functions in m-files may be a complicated and messy endeavor, but here's one way I came up with...
First, make your anonymous functions and put their handles in a cell array:
fcn1 = #() ...;
fcn2 = #() ...;
fcn3 = #() ...;
fcnArray = {fcn1 fcn2 fcn3};
...or, if you have functions already defined (like in m-files), place the function handles in a cell array like so:
fcnArray = {#fcn1 #fcn2 #fcn3};
Then you can make a new anonymous function that calls each function in the array using the built-in functions cellfun and feval:
foo = #() cellfun(#feval,fcnArray);
Although funny-looking, it works.
EDIT: If the functions in fcnArray need to be called with input arguments, you would first have to make sure that ALL of the functions in the array require THE SAME number of inputs. In that case, the following example shows how to call the array of functions with one input argument each:
foo = #(x) cellfun(#feval,fcnArray,x);
inArgs = {1 'a' [1 2 3]};
foo(inArgs); %# Passes 1 to fcn1, 'a' to fcn2, and [1 2 3] to fcn3
WORD OF WARNING: The documentation for cellfun states that the order in which the output elements are computed is not specified and should not be relied upon. This means that there are no guarantees that fcn1 gets evaluated before fcn2 or fcn3. If order matters, the above solution shouldn't be used.
The anonymous function syntax in Matlab (like some other languages) only allows a single expression. Furthermore, it has different variable binding semantics (variables which are not in the argument list have their values lexically bound at function creation time, instead of references being bound). This simplicity allows Mathworks to do some optimizations behind the scenes and avoid a lot of messy scoping and object lifetime issues when using them in scripts.
If you are defining this anonymous function within a function (not a script), you can create named inner functions. Inner functions have normal lexical reference binding and allow arbitrary numbers of statements.
function F = createfcn(a,...)
F = #myfunc;
function b = myfunc(...)
a = a+1;
b = a;
end
end
Sometimes you can get away with tricks like gnovice's suggestion.
Be careful about using eval... it's very inefficient (it bypasses the JIT), and Matlab's optimizer can get confused between variables and functions from the outer scope that are used inside the eval expression. It's also hard to debug and/or extent code that uses eval.
Here is a method that will guarantee execution order and, (with modifications mentioned at the end) allows passing different arguments to different functions.
call1 = #(a,b) a();
call12 = #(a,b) call1(b,call1(a,b));
The key is call1 which calls its first argument and ignores its second. call12 calls its first argument and then its second, returning the value from the second. It works because a function cannot be evaluated before its arguments. To create your example, you would write:
foo = #() call12(functionCall1, functionCall2);
Test Code
Here is the test code I used:
>> print1=#()fprintf('1\n');
>> print2=#()fprintf('2\n');
>> call12(print1,print2)
1
2
Calling more functions
To call 3 functions, you could write
call1(print3, call1(print2, call1(print1,print2)));
4 functions:
call1(print4, call1(print3, call1(print2, call1(print1,print2))));
For more functions, continue the nesting pattern.
Passing Arguments
If you need to pass arguments, you can write a version of call1 that takes arguments and then make the obvious modification to call12.
call1arg1 = #(a,arg_a,b) a(arg_a);
call12arg1 = #(a, arg_a, b, arg_b) call1arg1(b, arg_b, call1arg1(a, arg_a, b))
You can also make versions of call1 that take multiple arguments and mix and match them as appropriate.
It is possible, using the curly function which is used to create a comma separated list.
curly = #(x, varargin) x{varargin{:}};
f=#(x)curly({exp(x),log(x)})
[a,b]=f(2)
If functionCall1() and functionCall2() return something and those somethings can be concatenated, then you can do this:
>> foo = #() [functionCall1(), functionCall2()]
or
>> foo = #() [functionCall1(); functionCall2()]
A side effect of this is that foo() will return the concatenation of whatever functionCall1() and functionCall2() return.
I don't know if the execution order of functionCall1() and functionCall2() is guaranteed.

Call a function with several properties of an object

For (MEX) function calls it would be really nice to pass several properties of one object at once. Instead of foo(myObj.propA, myObj.propB) I want something like foo(myObj.[propA,propB].
Is this even possible?
With structs it is possible to use the getfield() function to get the data from more than one field, e.g.:
getfield(myStruct, {index}, {'fieldA', 'fieldB'})
But unfortunately, the following attempt to get more than one property from an object results in an error (Index exceeds matrix dimensions):
getfield(myObj, {index}, {'propA', 'propB'})
Maybe the only possibility is to write a function which returns several output arguments:
[varargout] = getProps(object,propnames)
for p=1:numel(propnames)
varargout{p} = object.(propnames{p});
end
But if I call another function with that function as input, e.g. sum(getProps(myObj,propnames)) only the first output argument of getProps is passed and I fall into despair. Is there any other way?
For an object, you'd use get, not getfield (or dynamic access in a loop like you showed).
>> h = figure;
>> get(h,{'Position','Renderer'})
ans =
[1x4 double] 'opengl'
This doesn't work for all objects, but for MATLAB graphics objects it does work. To deal with any class, you can use your function, but with a custom cell output instead of varargout:
function C = getProps(object,propnames)
for p = 1:numel(propnames),
C{p} = object.(propnames{p});
end
Then inside whatever function you write, you can get a comma-separated list of all properties with C{:}, which will be suitable for a function that expects each property name input as a separate argument (e.g. C = getProps(myObj,propnames); x = myFun(h,C{:}).

Functions with a flexible list of ordered/unordered and labeled/unlabeled inputs in MATLAB

A lot of MATLAB functions have an input structure such as:
output = function MyFun(a,b,c,'-setting1',s1,'-setting2',s2,'-setting3',s3)
I am wondering how I should implement this kind of functionality in my own functions. To be precise, I would like to find out how I can create a function such that:
The function has a variable number of inputs N + M
The first N inputs are ordered and unlabeled. In the example above, N = 3. The first input is always a, second input is always b, third input is always c. The function input is variable in that users do not necessarily need to send b, c; when they do not then these can take on default (hardcoded) values. As far as I know, this type of functionality is generally handled via varargin.
The remaining M inputs are unordered, but labeled. In the example above, M = 3, the variables are s1,s2,s3 and their labels are setting1,setting2 and setting3 respectively, I would like for users to be able to specify these variables in whatever order they want. If users choose not to specify one of these inputs (i.e. setting1), then I would like my function to assign default values for s1.
One example of such a function is the dlmwrite function.
Ideally, I am looking for an approach that is typically used by MATLAB developers so that my code is easy to understand.
The InputParser class addresses all of these issues. You can specify any number of:
Required parameters (ordered, unlabeled)
Optional parameters (ordered, unlabeled)
String parameter-value pairs in any order (unordered, labeled)
A very clear tutorial with examples is provided by MathWorks. For a function defined as function printPhoto(filename,varargin), the example boils down to the following.
Create the inputParser:
p = inputParser;
Specify defaults and define validation criteria:
defaultFinish = 'glossy';
validFinishes = {'glossy','matte'};
checkFinish = #(x) any(validatestring(x,validFinishes));
defaultColor = 'RGB';
validColors = {'RGB','CMYK'};
checkColor = #(x) any(validatestring(x,validColors));
defaultWidth = 6;
defaultHeight = 4;
Define required/optional/parameter input names, set their default values and validation functions:
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 the inputs into a struct:
parse(p,filename,varargin{:});
Then you have the input arguments and their values in p.Results.
The InputParser class is used throughout newer MathWorks functions, so don't be afraid to use it yourself!

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)

MATLAB- passing a function handle parameter into another function as a handle

Working on an assignment involving Genetic Algorithms (loads of headaches, loads of fun). I need to be able to test differing crossover methods and differing mutation methods, to compare their results (part of the paper I have to write for the course). As such, I want to just pass the function names into the Repopulate method, as function handles.
function newpop = Repopulate(population, crossOverMethod, mutationMethod)
...
child = crossOverMethod(parent1, parent2, #mutationMethod);
...
function child = crossOverMethod(parent1, parent2, mutationMethod)
...
if (mutateThisChild == true)
child = mutationMethod(child);
end
...
The key point here is like 3, parameter 3: how do I pass mutationMethod down another level? If I use the # symbol, I get told:
"mutationMethod" was previously used as a variable,
conflicting with its use here as the name of a function or command.
If I don't use the # symbol, then mutationMethod gets called, with no parameters, and is quite unhappy.
While I am aware that yes, I could just rewrite my code to make it work differently, I'm now curious as to how to make it actually work.
Any help is greatly appreciated.
Actually just dont use the # symbol, use it when you call the Repopulate function instead.
Example:
function x = fun1(a,m)
x = fun2(a,m);
end
function y = fun2(b,n)
y = n(b);
end
which we call as:
> fun1([1 2 3], #sum)
6
Refer to the documentation for Passing Function Handle Arguments
Note you can check if the argument is a function handle by: isa(m,'function_handle'). Therefore you can make your function Repopulate more flexible by accepting both a function handle and a function name as a string:
function x = fun(a,m)
if ischar(m)
f = str2func(m);
elseif isa(m,'function_handle')
f = m;
else
error('expecting a function')
end
x = fun2(a,f);
end
which now can be called both ways:
fun1([1 2 3], #sum)
fun1([1 2 3], 'sum')