This question already has answers here:
How to execute multiple statements in a MATLAB anonymous function?
(5 answers)
Closed 5 years ago.
So I was trying to polish my input validation in MATLAB functions and in the process I ended up creating the following function that really makes my code cleaner. I put it here in full in case someone finds it useful:
function [] = callFunctions(varargin)
%callFunctions Calls a sequence of functions on their respective arguments.
% The inputs are expected as funcHdl1, {input1}, funcHdl2, {input2}, ...
% Then callFunctions calls sequentially func1(input1); func2(input2); ...
%% === INPUT VALIDATION ===
% Check that the callFunctions has at least one argument
message = 'The number of arguments must be positive.';
assert(nargin > 0, message);
% Check that the callFunctions has an even number of arguments
message = 'The number of arguments must be even.';
assert(mod(nargin,2)==0,message);
% Name the handles
numHandles = nargin/2;
handleNames = cell(1,numHandles);
inputNames = cell(1,numHandles);
for k=1:numHandles
handleNames{k} = 'handle';
handleNames{k} = cat(2, handleNames{k}, int2str(k));
inputNames{k} = 'input';
inputNames{k} = cat(2, inputNames{k}, int2str(k));
end
% Function to check that the inputs are function handles
isValidFunctionHdl = #(x) validateattributes(x, {'function_handle'}, {});
% Create an input parser
p = inputParser;
% Add all arguments to check if they are handles. Don't check the inputs.
for k=1:numHandles
p.addOptional(handleNames{k}, 0, isValidFunctionHdl);
p.addOptional(inputNames{k}, 0);
end
% Parse the input
p.parse(varargin{:});
%% === PROGRAM ===
% Evaluate all the functions on their inputs
for k=1:numHandles
feval(varargin{2*k-1},varargin{2*k}{:});
end
end
Now the last part called %% === PROGRAM === is the important part. It just evaluates the functions func1, func2, func3, ... on their respective inputs input1, input2, input3, ..., all of which are given as inputs to callFunctions. It is called as:
callFunctions(funcHdl1, {input1}, funcHdl2, {input2}, ...)
My question is simple: is there a native MATLAB function that does what callFunctions does? I use this during input validation (in combination with assert and validateattributes). So Ì intend to use callFunctions in nearly every function I write. I'd like to use the least custom functions possible for this.
Ben
EDIT: I didn't want to go into this to keep the post short. But yes there is a context where this seems necessary for me. This is when I do input validation with the input parser. I often need to check multiple conditions, like this (completely made up example):
% Made up function to illustrate context
function [] = myFunction(input)
% Create an input parser
p = inputParser;
% Create functions to validate input. Must be a 2d logical array with at least one false value
isValidArray = #(x) validateattributes(x, {'logical'}, {'2d'});
hasAtLeastOneFalse = #(x) assert(length(find(x)) < length(x), 'Must be at least one false.');
isValidInput = #(x) callFunctions( isValidArray, {x}, hasAtLeastOneFalse, {x} );
% Add the required input
p.addRequired('input', isValidInput);
% Parse the input
p.parse(input);
end
This makes my code much cleaner because it allows me to combine multiple validateattributes and assert statements in the call to addRequired.
There is nothing like this that I know of that already exists ... and I am not sure why there would be.
Basically you are trading this:
func1(input1);
func2(input2);
For this:
callFunctions(#func1, {input1}, #func2, {input2})
All I see this doing is a bunch of input checking that callFunctions was used correctly. Assuming each individual function is written well and has it own asserts etc ... I don't get the need for this at all. Besides making it harder to read.
You could either skip it entirely or just have a simple for loop for a list of FCN handles & inputs. Each function would handle its own errors and you wouldn't be adding a bunch of code around something that seems pretty straight forward.
EDIT:
To your example usage: Why not do something like this? To me this is much "cleaner" than your example which seems to be your goal.
function [] = myFunction(input)
% Create an input parser
p = inputParser;
% Must be a 2d logical array with at least one false value
addRequired(p, 'input', #(x) validateattributes(x, {'logical'}, {'2d'}));
p.parse(input);
assert(length(find(input)) < length(input), 'Must be at least one false.')
disp('Running rest of code with good inputs!')
Which handles all your cases for bad inputs:
>> myFunction(ones(2,2,2))
Error using myFunction (line 6)
The value of 'input' is invalid. Expected input to be
one of these types:
logical
Instead its type was double.
>> myFunction(true(2,2,2))
Error using myFunction (line 6)
The value of 'input' is invalid. Expected input to be two-dimensional.
>> myFunction(true(1,2))
Error using myFunction (line 7)
Must be at least one false.
>> myFunction([true false])
Running rest of code with good inputs!
Related
In a Matlab script I call a user-defined function (m-function). My function returns a value while printing the value to the command window using disp and/or fprintf calls.
When writing an expression or a statement, one puts ; at its end to suppress printing. When the expression calls my function, the ; can suppress the printing of the returned value. However, this does not effect the disp output from within the function called.
I want to eliminate the display output of the function when appropriate. Is there a way to determine whether a function call was made in an expression ending with ;?
I like the spirit of what you're trying to do, but I think that it probably goes against the common programming patterns in Matlab. As you correctly state, the purpose of the terminating semicolon is to supress printing of returned values. Trying to get it to incorporate your other feature might well require some deep hacking and ugly hard-to-maintain code. The standard way to implement what you describe is via property name-value pair arguments. For example, Matlab's optimization suite has a property called 'Display' that can be set to various values to indicate the desired level of verbosity (see optimset).
If you want to try looking for a way to check for terminating semicolons, you might look into the undocumented mint, mlintmex, and mtree functions – read more here. Unfortunately, using mlint to simply check for the "Terminate statement with semicolon to suppress output" warning (see this function on the MatlabCental File Exchange) won't work in all cases as a function call by itself doesn't produce this warning.
Update
Here's an attempt at code that could be inserted into a called function to determine if the line of the caller is terminated by a semicolon. You should be aware that this has not been thoroughly tested and is likely very fragile. I have not tested it with sub-functions or anonymous functions and I know that it fails if you wrap a line over multiple lines using ....
st = dbstack('-completenames'); % M-file of caller and line number
caller = st(2);
str = mlint('-lex',caller.file); % Struct containing parsed data
isSemicolon = false; % Assume no semicolon
for i = 1:length(str)
% Find end-of-line corresponding to function call
c = strsplit(str(i).message,'/');
if str2double(c{1}) == caller.line && strcmp(c{2}(end-5:end-1),'<EOL>')
% Check for comments
j = i-1;
if ~isempty(strfind(str(j).message,'%'))
j = j-1;
end
% Check for semicolon
if strcmp(str(j).message(end-2),';')
isSemicolon = true; % Semicolon found
break;
end
end
end
In other words, play around with this to learn, but I would not recommend actually using it.
I'm afraid that the answer to your question is no. That information is simply not passed on to the function being called.
You shouldn't think about adding the semicolon as a means to "suppress printing", but rather that the lack of a semicolon instructs MATLAB to call the display function on the output variables of the function call. In other words, MATLAB interprets this code:
y = myFunc(x)
as:
y = myFunc(x);
display(y);
I think adding a 'print' or 'verbose' parameter to your function is your best bet for achieving what you want.
I think the simplest method to achieve the results you want (i.e. whether or not disp's get displayed) is to add an extra function input or output. For example, adding an input (optional, you can set default behaviour):
function y=myFunc(a,displayResults)
if nargin==1
displayResults=true; %// set the default behaviour
end
%// if you want to print something
if displayResults
disp(a)
end
end
Or an extra output. In this case foo produces no output to the screen, but all the messages are saved into a cell array, which can be accessed if desired:
function [x,m] = foo(a)
m={}; %// initialise cell array of output messages
x=a;
m{length(m)+1}=a; %// some message
m{length(m)+1}='another message'; %// another message
end
I think the first option will be better, the second will not deal with fprintf well, and displaying elements of m could be tricky depending on what it contains. The first method is very simple, and does not even require you to change existing code, as you can make the displayResults input optional and set the default to be what you want.
You may suppress disp outputs by locally redefining it at the beginning of the function:
function [] = hideDisplay()
%[
% Override `disp` behavior
disp = #(x)doNothing;
% Next `disp` calls will no longer appear in matlab console
disp('Hello')
disp('World!')
%]
end
%% ---
function [] = doNothing()
%[
%]
end
Here's a possible workaround (to be clear - this is not a real answer to the question per-se, just a way to avoid the unwanted behaviour). Say my function is:
function y = prt_test(x)
y = x + 1;
disp('IN PRT_TEST')
end
Calling:
>> % Regular use - message and output are displayed:
>> y = prt_test(1)
IN PRT_TEST
y =
2
>> % Regular use w/ ";" - only message is displayed:
>> y = prt_test(2);
IN PRT_TEST
>> % Use "evalc()" - message and output are displayed:
>> evalc('y = prt_test(3)')
ans =
IN PRT_TEST
y =
4
>> % Use "evalc()" w/ func ";" - only message is displayed:
>> evalc('y = prt_test(4);')
ans =
IN PRT_TEST
>> % Use "evalc();" - no output:
>> evalc('y = prt_test(5)');
>> % Use "evalc();" w/ func ";" - no output:
>> evalc('y = prt_test(6);');
>>
I have a set of functions that takes a cell array of tables and plots data from each table as a subplot on a figure. I have been learning to use the inputParser class to handle varargin inputs, and have that here. The optional parameters are for choosing plot type (plot or bar) and for choosing the names of the variables to plot from the input tables.
In my scenario, the inputs need to be passed along about 3 functions deep, so I'm wondering about best practices for doing this. In my current setup, the outermost function (main) takes a varargin input and parses the inputs by assigning defaults and such. Then I'm wondering, when it comes time to pass these inputs to the next function, is it best to pass the parsedInputs data Results struct down the line, or is it better to have the next function also take a varargin argument and to repeat the parsing process again? I'm not sure what the best way to go about this is. My code is below. The main script for test purposes looks as follows:
% RUN TEST CASE
Tables{1} = table([1 2 3]' , [6 7 8]', 'VariableNames', {'diam', 'length'});
Tables{2} = table([1 2 6]' , [6 9 2]', 'VariableNames', {'diam', 'length'});
Tables{3} = table([3 9 11]', [7 4 1]', 'VariableNames', {'diam', 'length'});
main(Tables);
The main function takes a (required) cell array of tables (Tables) and variable argument parameters, such as 'xVariable', 'yVariable', 'plotType'.
function main(Tables, varargin)%PlotParams, DICTS)
% parse inputs
parsedInputs = parse_plot_inputs(Tables, varargin);
% create figure of subplots
figure;
make_subplots_from_tables(parsedInputs);
end
A parse_plot_inputs function takes care of the default value assignment, etc.:
function parsedInputs = parse_plot_inputs(Tables, vararginList)
% input parser function for this specific plotting case
p = inputParser;
addRequired(p, 'Tables', #iscell);
addParameter(p, 'xVariable', 'diam');
addParameter(p, 'yVariable', 'length');
addParameter(p, 'plotType', 'plot');
parse(p, Tables, vararginList{:});
parsedInputs = p;
end
make_subplots_from_tables then loops through the cell array of tables, and calls plot_special to plot each of them on its own subplot.
function make_subplots_from_tables(parsedInputs)
% unpack parsed inputs
Tables = parsedInputs.Results.Tables;
% plot each table as a subplot
numTables = length(Tables);
for i = 1:numTables
subplot(numTables, 1, i); hold on;
plot_special(Tables{i}, parsedInputs)
end
end
plot_special is the "base" function in this scenario that calls the MATLAB plot functions:
function plot_special(T, parsedInputs)
% unpack parsed inputs
xVariable = parsedInputs.Results.xVariable;
yVariable = parsedInputs.Results.yVariable;
plotType = parsedInputs.Results.plotType;
% plot single table on one plot
xVals = T.(xVariable);
yVals = T.(yVariable);
switch plotType
case 'plot'
plot(xVals, yVals, '-x');
case 'bar'
bar(xVals, yVals);
otherwise
error('invalid plot type');
end
end
I am unsure whether this is the best method for taking in arguments and for using them in subsequent functions. This method works, although I'm not sure that it's the best practice, nor the most flexible, for example, considering the scenario when I would like to use plot_special on its own, and would like to be able to pass it arguments for xVariable, yVariable, etc. if need be. Given that it is currently dependent on the parsedInputs list from the main function, that wouldn't be doable. However, I'm unsure what another way to define it would be. I considered having an if statement built in along with a varargin input argument that checks whether the varargin is an already-parsed struct, or if it's getting the variables directly and needs to call the parse_plot_inputs itself to get things working. Any advice would be great.
There is no single "best" method, it all depends on circumstances. What you are doing is fine if the functions that take an inputParser object are private sub-functions. If they are generic functions that should work independently, they should have their own argument parsing. One thing you could do, given that you want plot_special to be a stand-alone function, is as follows:
function main(Tables, varargin)
figure;
make_subplots_from_tables(Tables, varargin{:});
end
function make_subplots_from_tables(Tables, varargin)
% plot each table as a subplot
numTables = length(Tables);
for i = 1:numTables
subplot(numTables, 1, i); hold on;
plot_special(Tables{i}, varargin{:})
end
end
function plot_special(T, varargin)
% parse `varargin` to yield `xVariable`, `yVariable`, `plotType`
% plot single table on one plot
end
This way you do the parameter parsing only where necessary, although it is done once for each table plotted, rather than only once for the whole graph. This is probably a very minor issue though, since parameter parsing is not nearly as expensive as plotting.
Is there any natural way to define a MATLAB function with multiple outputs that cannot or are inappropriate to "stack" into a matrix? For example, what if I want a function f that returns a 3x3 matrix A and a 4x4 matrix B?
I'm really surprised that this would even be an issue in MATLAB. Because in Python, all we need to do is return A, B which returns a tuple of the two. However it seems that MATLAB doesn't quite support the idea of containers. As a non-elegant workaround, I can use a struct to put the two pieces of data in, and the function goes something like:
function re = f(x)
%f: returns two dimensional-inconsistent matrices A and B
% function body as follows
....
A = ...;
B = ...;
% put data into the struct 're'
re.A = A;
re.B = B;
end
Apart from possible performance issues, this approach looks very unnatural and clumsy. Is there any better approach?
In MATLAB you can return any number of outputs with this syntax:
function [A,B] = f(x)
A = ...;
B = ...;
end
that is an even elegant solution than tuples used in python.
You can even control the behavior with the number of inputs and outputs (nargin and nargout) and discard outputs with a tilde. More information here.
I cannot think of a more elegant syntax.
Usually when having several outputs, one should declare the function as follows:
function [out1, out2, ... , outN] = funcName(in1,...,inM)
...
end
MATLAB also allows you to alter the behavior of your function based on the amount of requested inputs/outputs via the nargin/nargout functions, respectively (you can think of this as a form of overloading).
For example, you can specify as one of the inputs an array indicating which outputs you want the function to give, then populate the varargout cell array accordingly:
function varargout = funcName(in1,...,whichOut)
...
for indO = 1:numel(whichOut)
switch whichOut{indO}
case 'out1'
varargout{indO} = out1;
case 'out2'
... etc
case 'out6'
varargout{indO} = out6;
end
end
then call it using [out6, out1] = funcName(inp, {'out6','out1'});
See also varargin.
In a Matlab script I call a user-defined function (m-function). My function returns a value while printing the value to the command window using disp and/or fprintf calls.
When writing an expression or a statement, one puts ; at its end to suppress printing. When the expression calls my function, the ; can suppress the printing of the returned value. However, this does not effect the disp output from within the function called.
I want to eliminate the display output of the function when appropriate. Is there a way to determine whether a function call was made in an expression ending with ;?
I like the spirit of what you're trying to do, but I think that it probably goes against the common programming patterns in Matlab. As you correctly state, the purpose of the terminating semicolon is to supress printing of returned values. Trying to get it to incorporate your other feature might well require some deep hacking and ugly hard-to-maintain code. The standard way to implement what you describe is via property name-value pair arguments. For example, Matlab's optimization suite has a property called 'Display' that can be set to various values to indicate the desired level of verbosity (see optimset).
If you want to try looking for a way to check for terminating semicolons, you might look into the undocumented mint, mlintmex, and mtree functions – read more here. Unfortunately, using mlint to simply check for the "Terminate statement with semicolon to suppress output" warning (see this function on the MatlabCental File Exchange) won't work in all cases as a function call by itself doesn't produce this warning.
Update
Here's an attempt at code that could be inserted into a called function to determine if the line of the caller is terminated by a semicolon. You should be aware that this has not been thoroughly tested and is likely very fragile. I have not tested it with sub-functions or anonymous functions and I know that it fails if you wrap a line over multiple lines using ....
st = dbstack('-completenames'); % M-file of caller and line number
caller = st(2);
str = mlint('-lex',caller.file); % Struct containing parsed data
isSemicolon = false; % Assume no semicolon
for i = 1:length(str)
% Find end-of-line corresponding to function call
c = strsplit(str(i).message,'/');
if str2double(c{1}) == caller.line && strcmp(c{2}(end-5:end-1),'<EOL>')
% Check for comments
j = i-1;
if ~isempty(strfind(str(j).message,'%'))
j = j-1;
end
% Check for semicolon
if strcmp(str(j).message(end-2),';')
isSemicolon = true; % Semicolon found
break;
end
end
end
In other words, play around with this to learn, but I would not recommend actually using it.
I'm afraid that the answer to your question is no. That information is simply not passed on to the function being called.
You shouldn't think about adding the semicolon as a means to "suppress printing", but rather that the lack of a semicolon instructs MATLAB to call the display function on the output variables of the function call. In other words, MATLAB interprets this code:
y = myFunc(x)
as:
y = myFunc(x);
display(y);
I think adding a 'print' or 'verbose' parameter to your function is your best bet for achieving what you want.
I think the simplest method to achieve the results you want (i.e. whether or not disp's get displayed) is to add an extra function input or output. For example, adding an input (optional, you can set default behaviour):
function y=myFunc(a,displayResults)
if nargin==1
displayResults=true; %// set the default behaviour
end
%// if you want to print something
if displayResults
disp(a)
end
end
Or an extra output. In this case foo produces no output to the screen, but all the messages are saved into a cell array, which can be accessed if desired:
function [x,m] = foo(a)
m={}; %// initialise cell array of output messages
x=a;
m{length(m)+1}=a; %// some message
m{length(m)+1}='another message'; %// another message
end
I think the first option will be better, the second will not deal with fprintf well, and displaying elements of m could be tricky depending on what it contains. The first method is very simple, and does not even require you to change existing code, as you can make the displayResults input optional and set the default to be what you want.
You may suppress disp outputs by locally redefining it at the beginning of the function:
function [] = hideDisplay()
%[
% Override `disp` behavior
disp = #(x)doNothing;
% Next `disp` calls will no longer appear in matlab console
disp('Hello')
disp('World!')
%]
end
%% ---
function [] = doNothing()
%[
%]
end
Here's a possible workaround (to be clear - this is not a real answer to the question per-se, just a way to avoid the unwanted behaviour). Say my function is:
function y = prt_test(x)
y = x + 1;
disp('IN PRT_TEST')
end
Calling:
>> % Regular use - message and output are displayed:
>> y = prt_test(1)
IN PRT_TEST
y =
2
>> % Regular use w/ ";" - only message is displayed:
>> y = prt_test(2);
IN PRT_TEST
>> % Use "evalc()" - message and output are displayed:
>> evalc('y = prt_test(3)')
ans =
IN PRT_TEST
y =
4
>> % Use "evalc()" w/ func ";" - only message is displayed:
>> evalc('y = prt_test(4);')
ans =
IN PRT_TEST
>> % Use "evalc();" - no output:
>> evalc('y = prt_test(5)');
>> % Use "evalc();" w/ func ";" - no output:
>> evalc('y = prt_test(6);');
>>
Is it possible to get the 'nth' return value from a function without having to create dummy variables for all n-1 return values before it?
Let's say, I have the following function in MATLAB:
function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
Now suppose, I'm only interested in the third return value. This can be accomplished by creating one dummy variable:
[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
But I think this is kind of ugly. I would think that you might be able to do something like one of the following things, but you can't:
[_, _, variableThatIWillUse, _] = func;
[, , variableThatIWillUse, ] = func;
variableThatIWillUse = func(3);
variableThatIWillUse = func()(3);
Are there any elegant ways to do this that do work?
So far, the best solution is to simply use the variableThatIWillUse as a dummy variable. This saves me from having to create a real dummy variable that pollutes the work-space (or that I would need to clear). In short: the solution is to use the variableThatIWillUse for every return value up until the interesting one. Return values after can simply be ignored:
[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
I still think this is very ugly code.
With MATLAB Version 7.9 (R2009b) you can use a ~, e.g.,
[~, ~, variableThatIWillUse] = myFunction();
Note that the , isn't optional. Just typing [~ ~ var] will not work, and will throw an error.
See the release notes for details.
This is somewhat of a hack, but it works:
First a quick example function:
Func3 = #() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3
Now the key here is that if you use a variable twice on the left-hand side of a multiple-expression assignment, an earlier assignment is clobbered by the later assignment:
[b,b,c]=Func3();
% yields b=2, c=3
[c,c,c]=Func3();
% yields c=3
(Just to check, I also verified that this technique works with [mu,mu,mu]=polyfit(x,y,n) if all you care about from polyfit is the third argument.)
There's a better approach; see ManWithSleeve's answer instead.
If you wish to use a style where a variable will be left to fall into the bit bucket, then a reasonable alternative is
[ans, ans, variableThatIWillUse] = myfun(inputs);
ans is of course the default junk variable for MATLAB, getting overwritten often in the course of a session.
While I do like the new trick that MATLAB now allows, using a ~ to designate an ignored return variable, this is a problem for backwards compatibility, in that users of older releases will be unable to use your code.
I generally avoid using new things like that until at least a few MATLAB releases have been issued to ensure there will be very few users left in the lurch. For example, even now I find people are still using an old enough MATLAB release that they cannot use anonymous functions.
Here's another option you can use. First make a cell array to capture all the outputs (you can use the NARGOUT function to determine how many outputs a given function returns):
a = cell(1,3); % For capturing 3 outputs
% OR...
a = cell(1,nargout(#func)); % For capturing all outputs from "func"
Then call the function as follows:
[a{:}] = func();
Then simply remove the element from a that you want, and overwrite a:
a = a{3}; % Get the third output
I wrote a kth out function:
function kth = kthout(k, ffnc, varargin)
% kthout: take the kth varargout from a func call %FOLDUP
%
% kth = kthout(k, ffnc, varargin)
%
% input:
% k which varargout to get
% ffnc function to call;
% varargin passed to ffnc;
% output:
% kth the kth argout;
[outargs{1:k}] = feval(ffnc, varargin{:});
kth = outargs{k};
end %function
You can then call
val_i_want = kthout(3, #myfunc, func_input_1, func_input_2);
You could also wrap up the function like:
func_i_want = #(varargin)(kthout(3, #myfunc,varargin{:})); % Assuming you want the third output.
After which you use
val_i_want = func_i_want(func_input_1, func_input_2);
Note that there is overhead associated with using anonymous functions like this, and this is not something I would do in code that would be called thousands of times.
In MATLAB 2010a, I found a neat way of doing what you are asking for.
It is simply to use the character "~" (without the quotes of course) as your dummy variable (as many as you want when returning multiple parameters). This also works for input parameters to functions if the functions are designed to handle missing data.
I don't know if this existed in previous versions, but I just came across it recently.
You can make a function (or anonymous function) that only returns selected outputs, e.g.
select = #(a,b) a(b);
Then you can call your function like this:
select(func,2);
select(func,1:3);
Or you can assign the output to a variable:
output(1,2:4) = select(func,1:3);
I don't see any reason not to use ans(n). Like this:
size(rand([5 10 20 40]));
b = ans(2);
It gives b = 10, and this way would be compatible with all MATLAB versions. Note that size() here is just used to represent any function that has multiple return variables.
Furthermore, this works to get the second output argument when you don't know how many arguments there will be! Whereas, if you do this:
[~, b] = size(a);
Then b = 8000! (You need to end with ~, to catch more arguments!)