4

In a previous question, a user asked about iterating over a cell array of anonymous functions. I am wondering whether there is a way to evaluate a set of functions without the explicit use of a for loop.

As an example, the following code creates an array of (simple) functions, evaluates them for a fixed value and stores the results:

fcnList = {@(x) (x+1), @(x) (x+2)};
a = 2;
for i = 1:numel(fcnList)
    y(i) = fcnList{i}(a);
end

Is there a way to do this without looping?

Community
  • 1
  • 1
Ryan J. Smith
  • 1,140
  • 8
  • 15
  • 2
    I guess you could use [`cellfun`](http://www.mathworks.com/help/matlab/ref/cellfun.html) with [`feval`](http://www.mathworks.com/help/matlab/ref/feval.html) but I'm not really sure why avoiding a `for` loop matters in this case. `cellfun` might also be slower but I don't have MATLAB available to test at the moment. – sco1 May 23 '15 at 17:10
  • 1
    You're right that there are probably few use cases where this would significantly speed up execution. Still, it came up in a project and I figured it wouldn't hurt to ask. – Ryan J. Smith May 23 '15 at 17:12
  • 1
    To avoid a `for` loop or `cellfun` (which is more or less the same as a loop), you could define a _single_ function with _vector_ or _cell array_ output: `fcn = @(x) [x+1, x+2];` or `fcn = @(x) {x+1, x+2};`. Then `fcn(a)` gives you a vector or cell array cointaining the results. – Luis Mendo May 24 '15 at 02:09
  • @LuisMendo this is really useful. Please add this as an answer. – Ryan J. Smith May 24 '15 at 02:38

2 Answers2

5

For your example, you could do the following using the cellfun function:

fcnList = {@(x) (x+1), @(x) (x+2)};
a = 2;
cellfun(@(func) func(a),fcnList)
ans =

   3   4

Where I have created a handle called func which accepts as input a function from the fcnList variable. Each function is then evaluated for a.

If you need to pass a vector instead of a scalar, for instance b, you will need to set the 'UniformOutput' option to false:

b=[3 4]
fcnList = {@(x) (x+1), @(x) (x+2)};
cellfun(@(func) func(b),fcnList,'UniformOutput',false)
ans =
{
  [1,1] =
     4   5
  [1,2] =
     5   6
}
brodoll
  • 1,851
  • 5
  • 22
  • 25
3

To avoid a for loop or cellfun (which is more or less the same as a loop), you can define a single function with vector output:

fcn = @(x) [x+1, x+2];

Then fcn(a) gives you a vector cointaining the results:

>> fcn = @(x) [x+1, x+2];
>> a = 2;
>> fcn(a)
ans =
     3     4

If the results of each original function have different sizes you can define a single function with cell array output:

>> fcn = @(x) {x+1, [x+2; x+3]};
>> a = 2;
>> x = fcn(a)
x = 
    [3]    [2x1 double]
>> celldisp(x)
x{1} =
     3
x{2} =
     4
     5
Community
  • 1
  • 1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147