5

In Matlab, I was trying to put anonymous functions in an array:

>> a=[@(k)0.1/(k+1)    @(k)0.1/(k+1)^0.501]
??? Error using ==> horzcat
Nonscalar arrays of function handles are not allowed; use cell arrays
instead.

So I wonder what kinds of elements are allowed in an array, and in a cell array?

For example, I know that in an array, the elements can be numerical or strings. What else?

Andrey Rubshtein
  • 20,795
  • 11
  • 69
  • 104
Tim
  • 1
  • 141
  • 372
  • 590
  • Might be related - http://stackoverflow.com/questions/9055015/difference-between-accessing-cell-elements-using-and-curly-or-normal-brac/9055336#9055336 – Andrey Rubshtein Mar 13 '12 at 15:16

3 Answers3

6

In short: Cell array is a heterogeneous container, regular array is homogeneous. This means that in a regular array all of the elements are of the same type, whereas in cell array, they can be different. You can read more about cell array here.

Use cell array when:

  • You have different types in your array
  • You are not sure whether in the future you might extend it to another types
  • You are working with objects that have an inheritance pattern
  • You are working with an array of strings - almost in any occasion it is preferable to char(n,m)
  • You have a large array, and you often update a single element in a function - Due to Matlabs copy-on-write policy
  • You are working with function handles (as @Pursuit explained)

Prefer regular array when:

  • All of the elements have the same type
  • You are updating the whole array in one shot - like mathematical operations.
  • You want to have type safety
  • You will not change the data type of the array in the future
  • You are working with mathematical matrices.
  • You are working with objects that have no inheritance

More explanation about copy-on-write:

When you pass an array to a function, a pointer/reference is passed.

function foo(x)
     disp(x);
end

x= [1 2 3 4 5];
foo(x); %No copy is done here! A pointer is passed.

But when you change it (or a part of it), a copy is created.

function foo(x)
    x(4) = x(4) + 1;
end

x= [1 2 3 4 5];
foo(x); %x is being copied! At least twice memory amount is needed.

In a cell array, only the cell is copied.

function foo(x)
   x{4} = x{4} + 1;
end

x= {1 2 3 4 5}; %Only x{4} will be copied

Thus, if you call a function that changes a single element on a large array, you are making a lot of copies - that makes it slower. But in a cell array, it is not the case.

Community
  • 1
  • 1
Andrey Rubshtein
  • 20,795
  • 11
  • 69
  • 104
  • Thanks! I wonder what is "Malab copy-on-write policy" in "You have a large array, and you often update a single element in a function - Due to Malab copy-on-write policy"? – Tim Mar 14 '12 at 15:33
4

Function handles are actually the exception here, and the reason is that the Matlab syntax becomes surprising if you allow function handles to be a part of non-cell array. For example

a = @(x)x+1;
a(2);  %This returns 2

But, if arrays of function handles were supported, then

b = [@(x)x+1,  @(x)x+2];
b(2);                  %This would return @(x)x+2
b(3) = @(x)x+3;        %This would extend the size of the array

So then would this be allowed?

a(2) = @(x)x+2;       %Would this extend the size of the previously scalar array

Longwinded edit: This is documented in the release notes accompanying release R14, which was the first release allowing anonymous functions. Prior to R14 you could create function handles as references to m-file functions, and they could be placed in non-cell arrays. These could only be called using feval (e.g.: fnSin = @sin; output = feval(fnSin, pi)).

When anonymous functions were introduced, the Mathworks updated the syntax to allow a simpler calling convention (e.g. fnSin = @sin; output = fnSin(pi)) which had the effect of causing an ambiguity when using non-cell array of function handles. It looks like they did their best to grandfather this new behavior in, but those grandfathered conditions have certainly expired (this was 2004).

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Pursuit
  • 12,285
  • 1
  • 25
  • 41
2

The arrays can store only data with a fixed length. For instance, double, single, char, logical, integer. The reason is that (I guess) they are stored directly in a block of memory. On the other hand cells are stored as a list of pointers, each pointer can point to a data of different size.

That's why arrays cannot store strings, function handle, arrays, and multiple data types. Those type can have different length. For instance 'bla' has 3 bytes, 'blabla' has 6 bytes. Therefore if they are stored in the same memory block, if you want to change 'bla' into 'blabla' you would have to shift all the rest of the memory, which would be very slow, and so it's not handled.

Oli
  • 15,935
  • 7
  • 50
  • 66