Change default behavior of cellfun to 'UniformOuput' = false

9 views (last 30 days)
Is there a way to make 'UniformOuput' = false the default for cellfun and functions like it?
  2 Comments
Piotr Balik
Piotr Balik on 10 Nov 2022
@MathWorks Support Team is it possible to include this functionality in a patch for currently supported releases?
I think many users would be grateful, just they did not bother to escalate this further.

Sign in to comment.

Accepted Answer

Kelly Kearney
Kelly Kearney on 31 May 2017
I really wish this was an option too! I use cellfun all the time, and almost always with cell outputs required. This is one of those errors that bugs me because the solution is so easily automated. It bugs me enough that I wrote a kinda kludgy wrapper function to handle both cases; it just runs cellfun, and adds the 'UniformOutput'=0 flag if it fails the first time.
function varargout = celllfun(varargin)
varargout = cell(nargout,1);
try
[varargout{:}] = cellfun(varargin{:});
catch ME
if strcmp(ME.identifier, 'MATLAB:cellfun:NotAScalarOutput')
[varargout{:}] = cellfun(varargin{:}, 'uni', 0);
else
rethrow(ME);
end
end
This returns an array if possible, and a cell array otherwise:
>> a = celllfun(@(x) x(1:2), num2cell(rand(10,2),1))
a =
1×2 cell array
[2×1 double] [2×1 double]
>> a = celllfun(@(x) x(1), num2cell(rand(10,2),1))
a =
0.18675954426984 0.173883139944506
Here I've simply added an extra letter to the function name, so cellfun and celllfun coexist. You could use this function_handle function to do a true shadowing of the built-in to get this try-catch behavior as the default whenever cellfun is called.
  2 Comments
Stephen23
Stephen23 on 31 May 2017
Edited: Stephen23 on 31 May 2017
I am not totally convinced that this is a good solution...
  1. cellfun is already slower than calling a simple loop, yet this potentially doubles the runtime.
  2. having an uncontrollable special case is a bad way to write code. Scenario: someone writes some code using this function, and then one day it all stops working because the inputs just happened to be scalar that day and so this function outputs a numeric array instead of the expected cell array and it all goes belly up. This is not a robust way to write code. (For the same reason many experienced users always specify the dimension with max, min, size, etc, because their "special cases" are simply a pain in the proverbial. Special cases with plot have also caught me out, and are a pain to create a workaround for)
While this might be entertaining I would advise all users to avoid using this kind of kludge if they intend to write code that is actually robust and predictable. While it might require eight extra characters of typing, simply calling cellfun with the optional argument will be faster and most importantly totally reliable as to what output you will get:
cellfun(...,'uni',0)
will always return a cell array, and this is exactly what I would want my code to do.
Kelly Kearney
Kelly Kearney on 31 May 2017
Well, I did call it a kludgy wrapper, and there's a reason I don't include this one in my publicly-distributed code.
For me, this is a command-line only solution... I never include it in actual scripts or functions, and certainly not ones I'd intend to distribute.
But I get a lot of use out of cellfun when I'm doing data exploration type analysis from the command line... where one-liner is much more convenient than writing a loop, even if it's the less efficient option. You'd think by now it would be second nature for me to include the (..., 'uni', 0) option automatically... but nope, I leave it off all the time, get the error thrown, curse at myself, repeat cellfun call. The kludge just automates that workflow, and removes the cursing step. :-)

Sign in to comment.

More Answers (0)

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!