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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With