How to extract an element from a ''vector'' of function handle

Hi guys,
I'm having some troubles managing handle functions.
What I would like to do is to extract an element of an "handle" array like this below.
f = @(x1,x2,x3)[x1*2-x3;x3*x1-x2;x1-x2^2]
And I would like to compute "something" like that.
f(1) = x1*2-x3;
f(2) = x3*x1-x2;
f(3) = x1-x2^2;
So, like a vector.
How can I do that ??

 Accepted Answer

If you've already created your f function you could do this using one helper function. I vectorized your f function.
f = @(x1,x2,x3)[x1*2-x3;x3.*x1-x2;x1-x2.^2];
getRow = @(data, rowNum) data(rowNum, :); % Helper function
Now if you want a function handle that retrieves the third row in the output of f:
g3 = @(x1, x2, x3) getRow(f(x1, x2, x3), 3);
Check the full output versus the row 3 output:
y123 = f(1:5, 6:10, 11:15)
y123 = 3×5
-9 -8 -7 -6 -5 5 17 31 47 65 -35 -47 -61 -77 -95
y3 = g3(1:5, 6:10, 11:15)
y3 = 1×5
-35 -47 -61 -77 -95
You could theoretically eliminate the getRow function by explicitly calling subsref yourself inside g3, but using a separate getRow function makes the code much clearer IMO.

5 Comments

But now, a new problem has arisen.
Once I split the function handle with "getRow"
g1 = @(x1,x2,x3) getRow(fun(x1, x2, x3), 1);
g2 = @(x1,x2,x3) getRow(fun(x1, x2, x3), 2);
g3 = @(x1,x2,x3) getRow(fun(x1, x2, x3), 3);
Now I Cannot rearrange g1 g2 and g3 in a vector!
There is some way of doing this ?
Thank you in advance sir !
fun = @(x1,x2,x3)[x1*2-x3;x3.*x1-x2;x1-x2.^2];
getRow = @(data, rowNum) data(rowNum, :); % Helper function
g1 = @(x1,x2,x3) getRow(fun(x1, x2, x3), 1);
g2 = @(x1,x2,x3) getRow(fun(x1, x2, x3), 2);
g3 = @(x1,x2,x3) getRow(fun(x1, x2, x3), 3);
% Recombine
h = @(x1, x2, x3) [g1(x1, x2, x3); g2(x1, x2, x3); g3(x1, x2, x3)];
y123_fun = fun(1:5, 6:10, 11:15)
y123_fun = 3×5
-9 -8 -7 -6 -5 5 17 31 47 65 -35 -47 -61 -77 -95
y1 = g1(1:5, 6:10, 11:15)
y1 = 1×5
-9 -8 -7 -6 -5
y2 = g2(1:5, 6:10, 11:15)
y2 = 1×5
5 17 31 47 65
y3 = g3(1:5, 6:10, 11:15)
y3 = 1×5
-35 -47 -61 -77 -95
y123_h = h(1:5, 6:10, 11:15)
y123_h = 3×5
-9 -8 -7 -6 -5 5 17 31 47 65 -35 -47 -61 -77 -95
But obviously you're not going to want to do this splitting if the output of f has, say, 100 rows. In that case rather than having y1, y2, y3, ..., y100 have one function.
yfun = @(n, x1, x2, x3) getRow(fun(x1, x2, x3), n);
isequal(yfun(2, 1:5, 6:10, 11:15), ...
g2( 1:5, 6:10, 11:15)) % true
ans = logical
1
Ok but even so,
h = @(x1, x2, x3) [g1(x1, x2, x3); g2(x1, x2, x3); g3(x1, x2, x3)];
It's not a vector.
I would like to have a vector 3x1 [g1;g2;g3], but maybe it is not possible to convert an handle function to an array of size 3x1.
Or do you have an idea ?
Years ago MATLAB did allow you to have a vector of function handles, but that functionality was removed when we introduced anonymous functions (to avoid ambiguity: would f(3) be a call to the function with the input 3 or a request for the third element of the array?) If you want an array of function handles it must be a cell array.
Q = {@sin, @cos, @tan};
Now Q{2} is unambiguous and so is Q{2}(pi).
f = Q{2}(pi)
f = -1

Sign in to comment.

More Answers (1)

It seems like you want a cell array of function handles:
f = {@(x1,x2,x3)x1*2-x3; @(x1,x2,x3)x3*x1-x2; @(x1,x2,x3)x1-x2^2}
f = 3×1 cell array
{ @(x1,x2,x3)x1*2-x3} {@(x1,x2,x3)x3*x1-x2} { @(x1,x2,x3)x1-x2^2}
f{1}
ans = function_handle with value:
@(x1,x2,x3)x1*2-x3
f{2}
ans = function_handle with value:
@(x1,x2,x3)x3*x1-x2
f{3}
ans = function_handle with value:
@(x1,x2,x3)x1-x2^2
Then you can evaluate the functions one at a time:
f{1}(10,13,15)
ans = 5
f{2}(10,13,15)
ans = 137
f{3}(10,13,15)
ans = -159
Or all at once:
cellfun(@(x)x(10,13,15),f)
ans = 3×1
5 137 -159

3 Comments

This is from "doc function_handle"
With one exception, function handles can be manipulated and operated on in
the same manner as other MATLAB values, including assignment to variables
and inclusion in cells and structs. The exception is that you cannot
construct a function_handle array. The reason is that the parenthesis
notation for values of this class is used to call a function, not to
index an array. To achieve the effect of an array of function handles,
use cells, e.g., write "A = {@sin, @cos}" rather than "A = [@sin, @cos]".
Of course, you need to index A with braces: "A{i}".
Thank you guys for the answers.
But the function handle comes from some calculus and I cannot arrange as a cell array.
I made some calculus in syms "mode" and then, with the matlabFunction, I converted the result in a handle function.
The problem is that this result in handle function contains 3 functions
results = @(x1,x2,x3) [f1;f2;f3]
and so i wanted to extract f1 f2 f3 apart.
I see. Then maybe something like this would work, depending on what f1, f2 and f3 actually are:
% a function handle you have
results = @(x1,x2,x3) [f1;f2;f3]
results = function_handle with value:
@(x1,x2,x3)[f1;f2;f3]
% make it a char vector:
str = func2str(results)
str = '@(x1,x2,x3)[f1;f2;f3]'
% parse the char vector into argument list and functions f1, f2, f3:
f = regexp(str,'(@\(.+\))\[(.+);(.+);(.+)\]','tokens');
f = [f{:}]
f = 1×4 cell array
{'@(x1,x2,x3)'} {'f1'} {'f2'} {'f3'}
% make a cell array of function handles out of that argument list and each
% function (f1, f2, f3):
f = cellfun(@(x)str2func([f{1} x]),f(2:end),'UniformOutput',false)
f = 1×3 cell array
{@(x1,x2,x3)f1} {@(x1,x2,x3)f2} {@(x1,x2,x3)f3}
Now you have a cell array of function handles to those individual functions.

Sign in to comment.

Categories

Find more on Operators and Elementary Operations in Help Center and File Exchange

Products

Release

R2017b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!