Reputation: 7633
I would like to assign the values in a vector of length 2 to multiple variables. The output of size() is able to do this:
% works
[m,n] = size([0 0]);
However splitting this into two lines doesn't work:
sz = size([0 0]);
[m,n] = sz;
% returns:
% ??? Too many output arguments.
What is special about the return value of size that is lost when it is assigned to a variable?
Upvotes: 4
Views: 1196
Reputation: 112679
You could do it transforming sz
to a cell array, and then generating a comma-separated list from that array:
sz_cell = mat2cell(sz(:), ones(numel(sz),1));
[m, n] = sz_cell{:}; %// Or [m, n] = deal(sz_cell{:});
Upvotes: 2
Reputation: 14939
If you for some reason don't want to have this in a separate function, you can have an anonymous function return multiple outputs like this:
split = @(x) deal(x(1), x(2))
A = zeros(5,3)
sz = size(A)
[x, y] = split(sz)
x = 5
y = 3
The deal
function sees two left side arguments and thus produce the correct output. Note that this function will not respond well to wrong input and output. Check out Loren's blog for more information.
Upvotes: 3
Reputation: 25232
The custom function you introduced is quite an overkill and uses functions like eval
which are considered bad practice. It can be done much shorter. That's all you need:
function [ varargout ] = split( Vector )
varargout = num2cell( Vector );
end
And because of varargout
you have a variable-length output argument list and you don't need to edit your function for more argements.
It works for vectors as well as for matrices:
[a,b,c,d] = split( [1,2;3,4] )
a = 1
b = 3
c = 2
d = 4
If you don't like the matrix compatibility, include a condition and check the dimensions of the input vector.
Upvotes: 3
Reputation: 7633
I figured out a way to do this. Thanks to Will Robertson's answer I realized that writing a function was the only way to really get what I want. Here is split.
function [ o1, o2, o3, o4, o5, o6, o7, o8 ] = split( v )
%SPLIT Splits a vector of bounded length into individual return variables.
% Split() can handle arbitrarily long input vectors, but only a fixed
% number of output variables. @benathon
%
% Usage:
% vec = [1 2 3 4 5];
% [a,b,c,d,e] = split(vec);
% [f,g] = split(vec);
% If you would like to upgrade split() to handle more output variables,
% simply add more output variables to the function definition and
% then change this variable
maxout = 8;
[~,n] = size(v);
if n < nargout
error('input vector too short for number of output arguments');
end
% we only need to assign this many output variables
iterations = min(n,nargout);
% Matlab catches "Too many output arguments." before we can
%if( iterations > maxout )
% error('Too many output, edit split.m to easily upgrade');
%end
i = 1;
while i <= iterations
expression = sprintf('o%d=v(%d);', i, i);
eval(expression);
i = i + 1;
end
Look in the comments for usage. I've also made a gist: https://gist.github.com/esromneb/652fed46ae328b17e104
Upvotes: 0
Reputation: 5681
It isn't something special about the size value.It is just that it deals with sz as a single argument since you are copying to it the result of size and that's why it can't have 2 outputs.
You will get the same error by using any other function which defined by 1 output , for example : [m,n] = cos(0) etc..
Upvotes: 0
Reputation: 64570
Matlab's output arguments are interesting this way. A function can have a variable number of outputs depending on how many the ‘user’ asked for.
When you write
[m,n] = size([0 0]);
you are requesting two output arguments. Inside the function itself this would correspond to the variable nargout
equal to 2
.
But when you write
sz = size([0 0]);
the size
function recognises that it's a single output argument, and gives you both m
and n
as a vector instead of two singleton outputs.
This style of behaviour is (I think) generally uncommon in Matlab.
Also note that Matlab doesn't allow multiple arguments to break up vectors:
x = [1 1]
[y,z] = x
returns Too many output arguments.
Upvotes: 4