# What is the use of arrayfun if a for loop is faster?

This may not be so much of a scientific computing question but more of a MATLAB question, if that is the case, please feel free to close or migrate the question.

Root-finding problems are commonly encountered in scientific computing in various shapes and forms; but in this case, the goal is to solve a non-linear time-dependent PDE using operator splitting techniques. Without going into the details of the PDE problem (since it is irrelevant to my main question), the following lines are executed each time step:

S = arrayfun(@(x,y) fsolve(@(c)[x-c(1)-c(1)*c(2);y-c(1)*c(2)],rand(1,2),options),u,v, ...
'UniformOutput',false);


options is a structure to set the parameters of fsolve, u and v are column vectors of medium size (~8k or larger) and fsolve returns a vector (1 row by 2 columns) which necessitates the option (for arrayfun) UniformOutput to be set false. I can replace these two lines with the following for loop:

for i=1:length(u)
S(i,:) = fsolve(@(c)[u(i)-c(1)-c(1)*c(2);v(i)-c(1)*c(2)],rand(1,2),options);
end


This excerpt runs two times faster than the previous. The time difference even more significant if S is initialized ahead of time and transposed (so it aligns with column-major ordering of MATLAB). Apparently, this behaviour is expected since arrayfun just “hides” (internalizes) the for loop, and we have additional overhead introduced by the extra function handle.

Under this observation, what is the correct use case for the function arrayfun? If for loops are faster, why would someone use arrayfun? Especially when (arguably) for loops are easier to read?

Note: There are some nuances. For example, S as the output of arrayfun is a cell array in contrast to the n-by-2 matrix S we get from the for loop approach. So let's say that I don't care about the output, it could as well be dumped after computation. I am more interested in the reasons why someone would use arrayfun over a for loop given that arrayfun is 2x slower.

Edit 1: Octave gives the following justification for arrayfun's existence: "This is useful for functions that do not accept array arguments.". But then follows up with "If the function does accept array arguments it is better to call the function directly. ", since they also only internalize the for loop. And at the end of the documentation, they say that the built-in @plus function is 60% faster than the anonymous function @(x,y) x+y. This is probably because @plus behaves more like C macros, so there is no additional function call overhead.

• Applying a function to each element of an array comes up in many situations. Wrapping this pattern into a function raises the level of abstraction: you do not need to think in loops, your intent is probably clearer. If you are familiar with Python, comprehensions do this, as well as the built-in map function. NumPy also applies a function on each element of an array.
• It allows MathWorks to implement this pattern efficiently. Although arrayfun is currently implemented with a for loop, this might change in the future. If MathWorks later decides to change the implementation, as soon as the function signature remains the same, no backward compatibility issue arises.
• It allows third-party to reimplement it, as it is already done in the Parallel Computing Toolbox. You would need to rewrite your code with parfor to achieve the same.
• I can see the parallel computing angle; however, for in the for loop I wrote above can be simply replaced by parfor. That would be the degree of rewriting I would need. Additionally, on a single core, there is no difference between for and parfor in MATLAB. So, if the goal is future proofing I could as well use parfor from the beginning. I guess you could argue that arrayfun can target GPUs and CPUs with a simple switch, but that would require significant rewrite by itself. For example, I would have to make all my arrays in to gpuArrays (which is more than adding par to for). May 30, 2021 at 14:00
• "both map and list comprehensions are abused to a point by some programmers that it is becoming a contentious issue. Especially the criticism focuses on inefficiency and unreadability" Python's list comprehensions are more efficient than bare for loops (in CPython, for loops are not JIT compiled, as opposed to MATLAB). The fact that a certain language feature is abused is not the fault of the language. For instance, old time MATLAB users tend to vectorize everything to a point when it becomes unreadable (they don't know about JIT compilation). Similar observation for function handles. May 30, 2021 at 19:25