Thanks in advance,
I want to write a new Matlab function code with different options for sub-algorithms for two distinct steps dealing the input argument/s. An example of one solution can be illustrated by use of switch-case statement such as:
function Return = Calculator(input,option1,option2)
switch option1
case 'Algorithm1_Opt1'
sub=f_Algorithm1_Opt1(input)
case 'Algorithm2_Opt1'
sub=f_Algorithm2_Opt1(input)
end
switch option2
case 'Algorithm1_Opt2'
Return=f_Algorithm1_Opt2(sub)
case 'Algorithm2_Opt2'
Return=f_Algorithm2_Opt2(sub)
end
My question: is there a way to specify custom options structure for an user-defined function as in optimset like;
options = optimset('param1',value1,'param2',value2,...)
such as;
options = optimset('Display','iter','TolX',1e-8)
So at last, I want to call my function as;
Return_exp=Calculator(input_exp,'option1','Algorithm1_Opt1','option2','Algorithm2_Opt2')
Regards.
As others have pointed out you can use the inputParser class or varargin. The inputParser implementation is sometimes too simplistic for coding complex problems. I usually prefer using varargin in these circumstances. Below are some templates I used.
For parameter parsing in functions:
function output=myfunc(requiredArg1,requiredArg2,varargin)
%% Parse Param-Value Inputs
PARAM_NAMES={'name1','name2'};
PARAM_VALUES={value1_default,value2_default};
n=1;
N=numel(varargin);
while n<N
% Read parameter name.
if ischar(varargin{n}) && isrow(varargin{n})
tf=strcmpi(varargin{n},PARAM_NAMES);
if any(tf)
% Set parameter value.
PARAM_VALUES{tf}=varargin{n+1};
else
error('Unrecognized parameter name.');
end
else
error('Unrecognized input. Parameter name must be a string.');
end
n=n+2;
end
if n<=N
warning('An extra input argument was provided, but is ignored.');
end
%% Program
end
For parameter parsing in constructors for handle classes:
methods
function obj=ObjectName(requiredArg1,requiredArg2,varargin)
%% Set Object Properties Using Param-Value Inputs
n=1;
N=numel(varargin);
while n<N
% Read property name.
if ischar(varargin{n}) && isrow(varargin{n})
mp=findprop(obj,varargin{n});
if isempty(mp)
error('''%s'' is not a property of the %s class.',varargin{n},class(obj));
elseif strcmpi(mp.SetAccess,'public')
obj.(varargin{n})=varargin{n+1};
else
error('Denied access to set the ''%s'' property.',varargin{n});
end
n=n+2;
end
end
if n<=N
warning('An extra input argument was provided, but is ignored.');
end
%% Program
end
end
The first template can be also be used for parameter parsing in constructors for value classes by setting PARAM_NAMES=properties(obj).
Related
I would like to use inputParser on the function f(a,b,c,d), where a is mandatory and b-d are optional. I would like to keep b-d named = not use f(a, varargin), because that varargin doesn't tell you anything when you actually want to use the function. The simple p.parse(a,b,c,d) obviously does not work unless all 4 parameters are given.
The only way I know how to do it is to use setDefaultValue(argname, value), and then use p.parse(...) for checks if needed. But is there a simple way to hack this using just inputParser (without tons of ifs)?
As a side question, there is no easy way to do named arguments like in C# in MATLAB, right? So I would have that f(a,b,c,d) and use as such. First argument is a, then b, then c ... But when the user wanted to call it like f(a, 'd', 3, 'c', 2), he could. In this example, he would keep default b and use 3 for d and 2 for c. Without tons of work on my side of course - I know how to do it, writing my own parsing of the thing, but I would like a simpler solution (like other person's parsing :))
Im going to give you an alternative answer: Don't be lazy, write docs.
If you do this:
function [out]= foo(a,b,c,d)
%FOO does foo things
%
% FOO(a,b) does very foo thins to a and b
%
% FOO(a,b,c) is quite foo-y on c also
%
% FOO(a,b,c,d) c and d are optional FOO things
if (nargin==3)
...
then if the user presses F1 or types help foo they will get all the information in the comments.
To have users able to put inputs such as foo(1,2,'d',5) in my code, I use the following "inputparser" for optional parameters:
function [c,d]=parse_inputs(argin)
opts= {'c','d'};
defaults=ones(length(opts),1);
% Check inputs
nVarargs = length(argin);
if mod(nVarargs,2)
error('InvalidInput','Invalid number of inputs')
end
% check if option has been passed as input
for ii=1:2:nVarargs
ind=find(ismember(opts,lower(argin{ii})));
if ~isempty(ind)
defaults(ind)=0;
else
error('InvalidInput',['Optional parameter "' argin{ii} '" does not exist' ]);
end
end
for ii=1:length(opts)
opt=opts{ii};
default=defaults(ii);
% if one option is not default, then extrac value from input
if default==0
ind=double.empty(0,1);jj=1;
while isempty(ind)
ind=find(isequal(opt,lower(argin{jj})));
jj=jj+1;
end
if isempty(ind)
error('InvalidInput',['Optional parameter "' argin{jj} '" does not exist' ]);
end
val=argin{jj};
end
switch opt
case 'c':
if default;
c=4;
else
c=val;
end
...
otherwise
error('InvalidInput',['Invalid input name:', num2str(opt),'\n No such option in SART()']);
end
end
Then The first thing I do inside foo is:
[c,d]=parse_inputs(varargin);
The first part of the question on how to handle varying number of inputs without varargin was answered well by Ander Biguri's answer.
Regarding the second part of the question on how to parse inputs in pairs, here is my simplified "input parser":
function parseVarargin( argin )
% Simplified function to parse varargin property-value pairs
% Read input arguments
if mod(numel(argin),2)
error('Uneven number of inputs')
end
for i = 1 : 2 : numel(argin)-1
if ~ischar(argin{i})
error('Properties must be strings')
end
isValid = evalin('caller', sprintf('exist(''%s'',''var'')', argin{i}));
if isValid && ~strcmp(argin{i},'MRX')
assignin('caller', argin{i}, argin{i+1})
else
error(['Undefined property %s. ', ...
'Please note case-sensitivity.'], argin{i});
end
end
To use it, simply set the default variable values and the call parseVarargin on varargin:
function foo( a, varargin )
%FOO general description
%
% Usage:
% foo(a)
% foo(a, 'property-value-pairs')
%
% Properties:
% b : This ...
% c : That ...
% Default property values
b = 1;
c = [];
% Read property-value paris
parseVarargin( varargin );
% Do other stuff
function [ muln, varargout ] = my_mul( varargin )
%MY_MUL This function is used to multiply numbers.
% My_mul function multiplies array of entered numbers, and outputs single
% solution.
% For example: my_mul(12, 2, 3, 5) gives ans = 360
if nargout >=1
disp('Error, wrong number of output arguments');
varargout{1} = 0;
return
end
if nargin <= 1
disp('Error, small number of input argumnets');
return
else
muln = 1;
for i = 1:nargin
muln = muln*varargin{i};
end
end
end
Hi, everyone, I'm just doing my assignment for uni and have a qiuck question.
How can I make this function to give an error if it is called with more than one output.(It meant to give only one) Thanks!
In your function definition, you have defined your function to allow for an unlimited number of outputs. The keyword varargout is a place-holder for a variable number of outputs.
As you have stated in your question, you only want one possible output which in your case looks to be muln. So if you simply remove varargout from your function definition, MATLAB should automatically throw an error if too many outputs are requested
function muln = my_mul(varargin)
If you ever do need to use varargout but want to place constraints on how many outputs are provided for any given scenario, you can check the number of output arguments that were requested using nargout and then throw an error with the error function.
if nargout > 4
error('my_mul:TooManyOutputs', 'Too many outputs requested');
end
My opinion is that if a return value is expected the function needs to throw. Otherwise the caller (function calling this function) will expect everything to be ok. Note that disp('Error') gives information to the developer, but it does not give the program any indication on what happens. More importantly, the information does not give any indication of where the error occurs. This can force the developer to do heavy debugging just to find the error, which is completely unnecessary.
The use of variable output arguments should only be used in case a different number of output arguments should be expected. An example is some customized plot function
function varargout = myplot(varargin)
filename = '';
idx = find(strcmp(varargin,'filename'));
if (~isempty(idx) && length(varargin)<idx+1 && ~ischar(varargin{idx+1}))
error('filename property must be followed by a directory');
elseif(~isempty(idx))
filename = varargin{idx+1};
varargin([idx,idx+1]) = [];
end
h = plot(varargin{:});
varagout{1} = h;
if (~isempty(idx))
save(filename, h);
end
varagout{2} = filename;
This function works as plot except it saves the figure to file in case a filename is specified. In case the developer needs the handle it will be returned and in case the developer wants the save directory it can be returned as well. None of these arguments are necessary though. The developer may want to use this function as a standard plot function and this means that the user may want to call myplot as myplot(x,y);which does not return a value. Further note that even if 'filename' is not specified, the function can still return 2 outputs. The second output may be an empty array of char, but two outputs for the caller will never cause a crash.
Also, note that no further error handling is required. The only unchecked crashes are in plot and save. How this is handled may be different for different users and this means that it only is reasonable to let the user catch the error and handle it (as he would have done if save or plot would have thrown).
Apart from this you may also want to have a check so that the number of output variables are within the correct range (in this case 0,1 or 2 outputs).
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
I made a Matlab function
function foo(argone, argtwo)
The begining of the function allow to have default choices for those variables if the function is called only with one or even zero arguments
function foo(argone, argtwo)
if(~exist('argone','var'))
argone = defaultargone;
end
if(~exist('argtwo', 'var'))
argtwo = defaultargtwo;
end
... % Rest of the code
We can call the function as
foo() % Default values are assigned to argone and argtwo
foo(myargone) % Default value given to argtwo
foo(myargone, myargtwo) % No default values are used
But how to be able to give default value to argone only?
If function is called with
foo(~, myargtwo)
no default values are used; argone get the null value (that is not the default value)
Thank you for your help
An alternate way would be to include the option for handling an empty input:
function foo(argone, argtwo)
if ~exist('argone','var')||isempty(argone)
argone = defaultargone;
end
if ~exist('argtwo','var')||isempty(argtwo)
argtwo = defaultargtwo;
end
Then any of these should work:
foo()
foo([],[])
foo(argone)
foo([], argtwo)
The language itself does not support such inputs. A common workaround uses parameter value pairs.
Usange would be
foo('myargone',1, 'myargtwo',2)
foo('myargtwo',3)
foo('myargone',4)
In your function, you have to use varargin and the input parser
I am trying to write a minimal function that can be called with a variable number of arguments but that will not throw a wrong number of arguments error if miscalled.
Here is where I start from :
function varargout=fname(varargin)
% FNAME
% Usage: output=fname(input)
% Arguments check
if(nargin~=1 || nargout~=1)
disp('Function fname requires one input argument');
disp('and one output argument');
disp('Try `help fname`');
varargout(1:nargout)={0};
return;
end
input=varargin{1};
output=input;
varargout(1)={output};
end
However this does not work as I would like it to. Is there a way to write a function that :
never throw a "wrong number of arguments" error (so that the rest of the execution can continue)
accepts variable number of input and output arguments and checks them inside the function
(maybe more tricky) if the number of input / output arguments is not correct, does not replace the value of the provided output arguments (so that any misplaced call does not erase the previous value of the output argument)
I am open to any suggestions / other methods.
Thank you for your help.
UPDATE: thanks to #Amro for his answer, I guess what I miss here is either a call by address of reference for Matlab functions or a way to interrupt a function without returning anything and without stopping the rest of the execution.
Here is one way to implement your function:
function varargout = fname(input,varargin)
%# FNAME
%# Usage: output=fname(input)
%%# INPUT
if nargin<1
varargout(1:nargout) = {[]};
warning('Not enough input arguments.'), return
end
if ~isempty(varargin)
warning('Too many input arguments.')
end
%%# YOUR CODE: manipulate input, and compute output
output = input;
%%# OUTPUT
varargout{1} = output;
if nargout>1
warning('Too many output arguments.')
varargout(2:nargout) = {[]};
end
end
Obviously you can customize the warning messages to your liking...
Also, if you want your function to simply print the message instead of issuing warnings, replace all WARNING calls with simple DISP function calls.
Examples of function call:
fname()
fname(1)
fname(1,2)
x = fname()
x = fname(1)
x = fname(1,2)
[x,y] = fname()
[x,y] = fname(1)
[x,y] = fname(1,2)
The above calls execute as expected (showing warning messages when applicable). One caveat though, in the last three calls, if the variable y already existed in the workspace prior to the calls, it would be overwritten by the empty value y=[] in each...
If I understand your question correctly, then the answer is no. If a caller calls a function like this:
[a, b, c] = fname('foo');
then fname is required to return (at least) three outputs. There's no way to tell MATLAB that it should leave b and c alone if fname only returns one output.