matlab function with argument not required - matlab

I create a function
function y = getValue(modelName, param, option)
open_system(modelName);
runModel(option);
y = getActiveFun(param);
end
I would like when calling this function to have the choice to pass or not argument option
from some other files I call the function with all arguments and sometimes I would like to call it without passing option argument ?
I would like to call : getValue(modelName, param) from other files
How could I do that ?

The simplest way to do this is to use the nargin variable:
function y = getValue(modelName,param,option)
open_system(modelName);
if (nargin < 3)
# No option passed, do something like
runModel('defaultOption')
else
# Option passed
runModel(option);
end
y = getActiveFun(param);
end
nargin is just the number of input arguments that were actually submitted. Thus, nargin == 3 indicates that the option parameter has been set, nargin < 3 that it has not been set.
Thus, you could now always call your function like
result = getValue('myModel', myParameter)
or with all parameters
result = getValue('myModel', myParameter, someOption)

While solutions with nargin are already given and more or less a standard usage within most MATLAB codebases, I think there is a nicer alternative that is more readable.
With nargin in big functions, you have to remember what argument 3 was exactly. Especially if you have more optional arguments, it becomes cumbersome to keep track or to allow that some optional arguments are passed, while others are not.
The first and easier solution is my personal alternative to nargin, and that is using the exist function:
function [output] = getValue(modelName,param,option, otherOption)
if ~exist('option', 'var') || isempty(option)
option = 'defaultValueForOption';
end
if ~exist('otherOption', 'var') || isempty(otherOption)
otherOption = 'defaultValueForOption';
end
% perform other actions
The advantage is that now all input-related code is at the beginning and it is more verbose as to what should be happening. You won't clutter your other code with that logic. And you can also supplement those if statements with validation of the input and fall back onto the default when an invalid option is given.
The other possibility is standard in later versions of MATLAB: the inputParser class. With this class, you can define even more complicated scenarios of optional parameters and even key-value pairs.
Below is a self-descriptive example I have kept to avoid needing the documentation every time.
%% Usage Example input Parser
%
function output = FuncName(rParam1, rParam2, oParam1, oParam2, varargin)
p = inputParser();
defaultValue = 0;
validatorFunc = #(x)(true); % validator function should return true when x is valid
%% Input Format definition
p.addRequired('rParam1', validatorFunc);
p.addRequired('rParam2', validatorFunc);
p.addOptional('oParam1', defaultValue, validatorFunc);
p.addOptional('oParam2', defaultValue, validatorFunc);
p.addParamValue('kvParam1', defaultValue, validatorFunc);
p.addParamValue('kvParam2', defaultValue, validatorFunc);
p.addParamValue('kvParam3', defaultValue, validatorFunc);
p.addParamValue('kvParam4', defaultValue, validatorFunc)
%% Optional Settings
% expand supplied struct to ParamValue pairs (or other arguments)
p.StructExpand = true; % default: false
%% Parse
p.parse(rParam1, rParam2, oParam1, oParam2, varargin{:})
%% Retrieve results
values = p.Results(); % structure with all values
defaultedArgs = p.UsingDefaults; % cell array of all parameter names using defaults
end
This approach is even more verbose and personally, I don't quite like the fact that one has to redefine for every input whether it is required or optional and that it requires quite a lot of boilerplate code. But at least, it is a solution that is a standard solution and without a doubt to be preferred for larger functions.
Both approaches do suffer from a drawback compared to the nargin way of checking: they are both slower. So if you use these in functions that get called a lot (or only perform a very quick calculaion), it might be more worthwhile to use nargin instead.

For completeness, lets see the basics (see documentation here).
In a function if an argument is not used, it is only a "programming warning", nothing more. So the problem is that you use a parameter that may or may not be provided.
So this is handled using
nargin % the number of parameters provided in current call
nargin(function_name) % the number of parameters the declaration has
So based on these you may program some conditions and include there the code that uses the non-standard input parameters.
For more complex cases varargin is most proper that handles variable length parameter list where the ordering may not be defined. But this is too much for this question

Look at the following link:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/65943
they have several suggestions

Related

How to test arguments for a figure or axis object in MATLAB 2022?

A function receives a figure or axis object object as parameter.
I want to test this as shown in the FIXME line.
Which test should be used here in order to allow all valid objects for exportgraphics?
% myexportgraphics.m
function myexportgraphics(f)
arguments
f (1,1) {}; % FIXME add a test here
end
exportgraphics(f,...);
end
This full list of validation functions is documented here:
https://uk.mathworks.com/help/matlab/matlab_prog/argument-validation-functions.html
The only relevant one for checking the input type (other than ones for specific types like "double") is mustBeUnderlyingType
You can check which types are valid using underlyingType on example objects you want to accept.
underlyingType( figure() ); % 'matlab.ui.Figure'
underlyingType( axes() ); % 'matlab.graphics.axis.Axes'
So this would check for figures
function myexportgraphics(f)
arguments
f (1,1) {mustBeUnderlyingType(f,'matlab.ui.Figure')};
end
end
However, that doesn't allow multiple variable types, so per the docs you probably want to make your own validation function
function myexportgraphics(f)
arguments
f (1,1) {mustBeExportGraphicsType(f)};
end
end
function mustBeExportGraphicsType(g)
if ~ismember( class(g), {'matlab.ui.Figure','matlab.graphics.axis.Axes'} )
eidType = 'mustBeExportGraphicsType:notExportGraphicsType';
msgType = 'Input must be a figure or axes object';
throwAsCaller(MException(eidType,msgType));
end
end
These are the requirements for a custom validation function, emphasis mine:
Functions used for validation have these design elements:
Validation functions do not return outputs or modify program state. The only purpose is to check the validity of the input value.
Validation functions must accept the value being validated as an input argument. If the function accepts more than one input argument, the first input is the value to be validated.
Validation functions rely only on the inputs. No other values are available to the function.
Validation functions throw an error if the validation fails. Using throwAsCaller to throw exceptions avoids showing the validation function itself in the displayed error message.
Creating your own validation function is useful when you want to provide specific validation that is not available using the MATLAB validation functions. You can create a validation function as a local function within the function file or place it on the MATLAB path.
As an aside, you could use ishghandle within the custom validation function which returns true for figure and axes inputs. If you didn't use the arguments validation syntax, you could instead use ishghandle with the slightly older inputParser approach to input validation, or a simple assert near the start of your function, but that's probably beyond the scope of this question.

equivalent of `evalin` that doesn't require an output argument (internally)

Background -- I was reading up on accessing shadowed functions, and started playing with builtin . I wrote a little function:
function klear(x)
% go to parent environment...
evalin('base', builtin('clear','x')) ;
end
This throws the error:
Error using clear
Too many output arguments.
I think this happens because evalin demands an output from whatever it's being fed, but clear is one of the functions which has no return value.
So two questions: am I interpreting this correctly, and if so, is there an alternative function that allows me to execute a function in the parent environment (that doesn't require an output)?
Note: I'm fully aware of the arguments against trying to access shadowed funcs (or rather, to avoid naming functions in a way that overload base funcs, etc). This is primarily a question to help me learn what can and can't be done in MATLAB.
Note 2
My original goal was to write an overload function that would require an input argument, to avoid the malware-ish behavior of clear, which defaults to deleting everything. In Q&D pseudocode,
function clear(x)
if ~exist('x','var') return
execute_in_base_env(builtin(clear(x)))
end
There's a couple issues with your clear override:
It will always clear in the base workspace regardless of where it's called from.
It doesn't support multiple inputs, which is a common use case for clear.
Instead I'd have it check for whether it was called from the base workspace, and special-case that for your check for whether it's clearing everything. If some function is calling plain clear to clear all its variables, that's bad practice, but it's still how that function's logic works, and you don't want to break that. Otherwise it could error, or worse, return incorrect results.
So, something like this:
function clear(varargin)
stk = dbstack;
if numel(stk) == 1 && (nargin == 0 || ismember('all', varargin))
fprintf('clear: balking at clearing all vars in base workspace. Nothing cleared.\n');
return;
end
% Check for quoting problems
for i = 1:numel(varargin)
if any(varargin{i} == '''')
error('You have a quote in one of your args. That''s not valid.');
end
end
% Construct a clear() call that works with evalin()
arg_strs = strcat('''', varargin, '''');
arg_strs = [{'''clear'''} arg_strs];
expr = ['builtin(' strjoin(arg_strs, ', '), ')'];
% Do it
evalin('caller', expr);
end
I hope it goes without saying that this is an atrocious hack that I wouldn't recommend in practice. :)
What happens in your code:
evalin('base', builtin('clear','x'));
is that builtin is evaluated in the current context, and because it is used as an argument to evalin, it is expected to produce an output. It is exactly the same as:
ans = builtin('clear','x');
evalin('base',ans);
The error message you see occurs in the first of those two lines of code, not in the second. It is not because of evalin, which does support calling statements that don't produce an output argument.
evalin requires a string to evaluate. You need to build this string:
str = 'builtin(''clear'',''x'')';
evalin('base',ans);
(In MATLAB, the quote character is escaped by doubling it.)
You function thus would look like this:
function clear(var)
try
evalin('base',['builtin(''clear'',''',var,''')'])
catch
% ignore error
end
end
(Inserting a string into another string this way is rather awkward, one of the many reasons I don't like eval and friends).
It might be better to use evalin('caller',...) in this case, so that when you call the new clear from within a function, it deletes something in the function's workspace, not the base one. I think 'base' should only be used from within a GUI that is expected to control variables in the user's workspace, not from a function that could be called anywhere and is expected (by its name in this case) to do something local.
There are reasons why this might be genuinely useful, but in general you should try to avoid the use of clear just as much as the use of eval and friends. clear slows down program execution. It is much easier (both on the user and on the MATLAB JIT) to assign an empty array to a variable to remove its contents from memory (as suggested by rahnema1 in a comment. Your base workspace would not be cluttered with variables if you used function more: write functions, not scripts!

Avoiding eval in matlab function

I use the symbolic toolbox in matlab to generate some very long symbolic expressions. Then I use matlabFunction to generate a function file.
Say there are three parameters: p1, p2 and p3.
I have a cell with strings {'p1', 'p2', 'p3'}.
In the derivation of the model I generate symbolic variables p1, p2 and p3 out of them using eval in a loop and stack them in a vector par.
Then when in matlabFunction, I specify par as input.
Moreover, I save the cell string in a .mat file.
Then when I want to simulate this model, I can construct this parameter array using that cell of strings from the .mat file out of 30 available parameters and their values.
Advantages: No need to keep track of the different parameters if I add one to . I can change the order, mess around, but older models still work.
Disadvantage:
Turning things into a function file leads to this error (psi is one of the parameters):
Error: File: f_derive_model.m Line: 96 Column: 5
"psi" previously appeared to be used as a function or
command, conflicting with its use here as the name of a
variable.
A possible cause of this error is that you forgot to
initialize the variable, or you have initialized it
implicitly using load or eval.
Apparently some unnescescary checking is going on because the variable will be intialized in an eval statement.
Question: How can I avoid eval but keep the list of parameters indepent from the model stuff.
Code deriving the long equations:
% Model parameters
mdl.parameters = {'mp','mb','lp','lb','g','d','mP','mM','k','kt'};
par = [];
for i=1:length(mdl.parameters)
eval(strcat(mdl.parameters{i}, '=sym(''', mdl.parameters{i}, "');"));
eval(sprintf(['par = [par;' mdl.parameters{i} '];']));
end
%% Calculate stuff
matlabFunction(MM,'file',[modelName '_mass'],'vars',{par},'outputs',{'M'});
Code using the generated file:
getparams
load('m3d_1')
par = [];
for i=1:length(mdl.parameters)
eval(sprintf(['par = [par;params.' mdl.parameters{i} '];']));
end
See how, as long as I specify the correct value to for example params.mp, it always gets assigned to the input corresponding to the symbolic variable mp in the par vector. I do not want to lose that and have to keep track of the order and so on, nor do I want to call my functions with all the parameters one by one.
Actually, I see nothing wrong in your approach even if the "public opinion" affirms that it's better to avoid using the eval function. An alternative would be using the assignin function as follows:
% use 'caller' instead of 'base' if this code runs within a function
for i = 1:numel(mdl.parameters)
var_name = mdl.parameters{i};
assignin('base',var_name,sym(var_name));
end
In the second case (the one concerning the par variable) I would instead use the getfield function:
par_len = numel(mdl.parameters);
par = cell(par_len,1);
for i = 1:par_len
par{i} = getfield(params,mdl.parameters{i});
end
or, alternatively, this approach:
par_len = numel(mdl.parameters);
par = cell(par_len,1);
for i = 1:par_len
par{i} = params.(mdl.parameters{i});
end

passing anonymous functions through inputParser (matlab)

I'm trying to use Matlab's inputParser for the first time, and I have to say I'm finding it a bit confusing. I am unable to successfully provide an anonymous function as an optional parameter.
This is the function I am passing arguments to
function myfun(str,bounds,varargin)
p = inputParser;
p.FunctionName = mfilename;
p.addRequired('str',#isstr);
p.addRequired('bounds',#isvector);
p.addOptional('str_latex','',#isstr);
p.addOptional('seed',[], #(x) isa(x,'function_handle'))
p.parse(str,bounds,varargin{:});
p.Results
% do something here
end
And I am calling it like this...
myfun('str', 'epsilon',...
'str_latex', '\epsilon',...
'bounds', [0 1],...
'seed', #() betarnd(2,2))
But I get an error:
Error using my fun
The value of 'seed' is invalid. It must satisfy the function: #(x)isa(x,'function_handle').
I suspect a simple error, but I cannot figure it out.
Name-value pairs are declared using the addParameter method (R2013b+, addParamValue prior to that). addRequired and addOptional do not have name-value pairs associated with them, simply identifying/documenting argname inputs for internal use and association with the parsed struct. It appears you want to use all addParamter-s in this use case.
The main idea behind the three input types is
Required: the very first arguments with explicit, documented inputnames that absolutely need to be supplied by the user for the function to perform properly.
Optional: arguments that typically follow Required arguments with explicit, documented inputnames that are often input by the user for customized behavior.
Name-Value: arguments that typically follow Optional arguments with a name specifying the value to be set are often input by the user for customized behavior but not so often as to be given an upfront, explicit parameter like Optional arguments.
In my experience, Required arguments are almost always obvious, for good, well-defined functions, while Optional and Name-Value is more experience-, complexity-, and aesthetics-based. A simple example would be linspace: the start and end of the interval are absolutely needed for the function to work, but not necessarily the number of points which can be left to 100 by default, but giving it an explicit name-value pair is a little overkill. A more complex example would be the plot function: at a minimum y data is needed, then x,y pairs of data, then x,y,linSpec sets of data, and then a whole list of specific name-value pairs for pinpoint customization that users can use if they so choose.
With your input parser as written, the call sequence should be:
myfun('epsilon',[0,1],'\epsilon',#() betarnd(2,2));
Since no name-value pairs were declared, none exist, but the Optional arguments still have a positional order associated with them. You can re-write your parser as:
function myfun(varargin)
p = inputParser;
p.FunctionName = mfilename;
p.addParameter('str',[],#isstr);
p.addParameter('bounds',[],#isvector);
p.addParameter('str_latex','',#isstr);
p.addParameter('seed',[], #(x) isa(x,'function_handle'))
p.parse(str, bounds, varargin{:});
p.Results
% do something here
end
For something like the generic input sequence you may have been expecting. Notice that I used []-s to fail the simple validations without a good error message; you should add a good error message indicating that those name-value pairs are required for proper functionality, or do as you were doing and have explicit, upfront Required inputs with addRequired but without the name-value semantics.

Anonymous functions calling functions with multiple output forms

I'm trying to define an anonymous function that calls a version of a function that returns multiple outputs.
For example, the function find has two possible output forms:
[row,col] = find(X);
and
[ind] = find(X);
Say I would like to choose the first form inside of an anonymous function.
I have tried
1)
get_columns = #(x) x(2);
and 2)
get_columns = #(x,y) y;
But when I call:
get_columns(find(x))
The first version of get_columns thinks I am calling find as [ind] = find(X) and not as [row,col] = find(X);, while the second one complains with "Not enough input arguments".
Is there a way to trigger a specific output form of a function inside an anonymous function?
Directly, no. Unfortunately, there are a number of features which are inaccessible via anonymous functions, and accessing multiple output arguments is one of them. (The other one I frequently find is that you cannot define an if statement inside an anonymous function. This appears to be a limitation of Matlab syntax more than anything else.
However, a pretty simple helper function can make this possible.
function varargout = get_outputs(fn, ixsOutputs)
output_cell = cell(1,max(ixsOutputs));
[output_cell{:}] = (fn());
varargout = output_cell(ixsOutputs);
This function takes a function handle plus an array of output indexes, and returns the indexed outputs.
If you create this file (hopefully better commented) and put it on your path, then you can access the second output of the find function as by defining the following function
find_2nd = #(x)get_outputs(#()find(x),2)
And now you can find the find the indexes of an array which equal 1 as
>> find_2nd([4 3 2 1]==1)
ans =
4
And now you should be able to access alternative output arguments at-will from within anonymous functions.
This get_outputs function above could be widely useful for brief anonymous functions. Very nice.
Also, regarding the comment that an "if" can't be used in MATLAB, this is only partially true. Identical behavior can easily be implemented anonymously. For instance, here's an anonymous if:
anonymous_if = #(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();
Use:
out = anonymous_if(condition1, action1, condition2, action2, ...);
The action corresponding to the first true condition is executed. For instance, this prints 'hello'.
anonymous_if(false, #() disp('hi'), ... % if false, print 'hi'
true, #() disp('hello')) % else if true, print 'hello'
Granted, it's a bit complicated at first sight, but I keep something like this on my path so I can use an "if" in an anonymous function. Much more complex anonymous functions can be built in this way.