123

Is it possible to get the 'nth' return value from a function without having to create dummy variables for all n-1 return values before it?

Let's say, I have the following function in MATLAB:

function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;

Now suppose, I'm only interested in the third return value. This can be accomplished by creating one dummy variable:

[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;

But I think this is kind of ugly. I would think that you might be able to do something like one of the following things, but you can't:

[_, _, variableThatIWillUse, _] = func;

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

Are there any elegant ways to do this that do work?


So far, the best solution is to simply use the variableThatIWillUse as a dummy variable. This saves me from having to create a real dummy variable that pollutes the work-space (or that I would need to clear). In short: the solution is to use the variableThatIWillUse for every return value up until the interesting one. Return values after can simply be ignored:

[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;

I still think this is very ugly code.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jordi
  • 5,846
  • 10
  • 40
  • 41
  • Aside from using a cell array as I described in my answer, repeating the variable name is probably your only other solution. Hopefully your variable names aren't as long as "variableThatIWillUse". =) – gnovice Apr 14 '09 at 13:40
  • Actually they are. 'dummy' was just an example. Normally I would use 'variableThatIWillNotUse'. Other variables are named 'variableThatIMightUse', 'variableThatIWillUse2' and 'variableThatCanBarelyFitOnA80CharacterLine'. I'm researching the correlation between long names and homicide ratings. ;) – Jordi Apr 14 '09 at 14:12
  • 27
    Actually since R2009b ignoring function returns is solved more elegantly using the '~'-Char. e.g.: [~,b] = sort(rand(10,1)) – ymihere Oct 09 '09 at 06:12
  • 1
    FOR NEW READERS: ^ should be the correct answer. See [ManWithSleeve's answer](http://stackoverflow.com/a/1404597/44330) below – A.Wan Sep 10 '15 at 22:19
  • 1
    In you example if you only want the 3rd output argument you shall use:[ variableThatIWillUse,variableThatIWillUse,variableThatIWillUse] = func; No need to clear a dummy variable. For newer MATLAB versions >=R2009b, use [~,~,variableThatIWillUse] = func; – Thierry Dalon Sep 20 '16 at 06:37

8 Answers8

239

With MATLAB Version 7.9 (R2009b) you can use a ~, e.g.,

[~, ~, variableThatIWillUse] = myFunction();

Note that the , isn't optional. Just typing [~ ~ var] will not work, and will throw an error.

See the release notes for details.

pauldoo
  • 18,087
  • 20
  • 94
  • 116
ManWithSleeve
  • 2,647
  • 2
  • 15
  • 5
40

This is somewhat of a hack, but it works:

First a quick example function:

Func3 = @() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3

Now the key here is that if you use a variable twice on the left-hand side of a multiple-expression assignment, an earlier assignment is clobbered by the later assignment:

[b,b,c]=Func3();
% yields b=2, c=3

[c,c,c]=Func3();
% yields c=3

(Just to check, I also verified that this technique works with [mu,mu,mu]=polyfit(x,y,n) if all you care about from polyfit is the third argument.)


There's a better approach; see ManWithSleeve's answer instead.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • 8
    Had not thought about solving it like this. However, I feel this solution sacrifices the clarity of intent for cleverness. – Jukka Dahlbom Apr 14 '09 at 13:07
  • 5
    I personally just use [junk, junk, c] = function_call() and assume both that "junk" is never an important variable and if it contains a lot of memory that I will clear it if necessary. – Jason S Apr 14 '09 at 13:13
  • 5
    to the downvoter: Why the -1? This answer was written before R2009b was even released, so @ManWithSleeve's answer wouldn't have worked at the time. Now, of course, that's the right approach. – Jason S Sep 20 '11 at 14:37
  • 2
    Maybe a comment in the first line of your answer would be helpful? I just came here through google, so it seems it's worth updating. – FvD Apr 23 '13 at 05:05
  • The left-to-right assignment is not officially guaranteed by The MathWorks, so you probably shouldn't rely on using c after [c,c,c] = myFunc(). (See Comment #26 here: http://blogs.mathworks.com/loren/2009/09/11/matlab-release-2009b-best-new-feature-or/) – Matt Krause Aug 07 '13 at 17:09
  • You should simply use the tilde `~` operator, per documentation: https://www.mathworks.com/help/matlab/matlab_prog/ignore-function-outputs.html – Tom Charles Zhang Apr 07 '21 at 03:33
37

If you wish to use a style where a variable will be left to fall into the bit bucket, then a reasonable alternative is

[ans, ans, variableThatIWillUse] = myfun(inputs);

ans is of course the default junk variable for MATLAB, getting overwritten often in the course of a session.

While I do like the new trick that MATLAB now allows, using a ~ to designate an ignored return variable, this is a problem for backwards compatibility, in that users of older releases will be unable to use your code.

I generally avoid using new things like that until at least a few MATLAB releases have been issued to ensure there will be very few users left in the lurch. For example, even now I find people are still using an old enough MATLAB release that they cannot use anonymous functions.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 7
    Yes, it's clever, but the native Matlab editor will give a warning if you assign anything to the ans variable. I don't think having warnings are very elegant... – Jordi Apr 16 '09 at 15:00
  • 11
    You can turn the warning off. End the line with this comment string %#ok Mlint will then ignore this. No warnings. –  Apr 25 '09 at 00:35
14

Here's another option you can use. First make a cell array to capture all the outputs (you can use the NARGOUT function to determine how many outputs a given function returns):

a = cell(1,3);  % For capturing 3 outputs
% OR...
a = cell(1,nargout(@func));  % For capturing all outputs from "func"

Then call the function as follows:

[a{:}] = func();

Then simply remove the element from a that you want, and overwrite a:

a = a{3};  % Get the third output
glglgl
  • 89,107
  • 13
  • 149
  • 217
gnovice
  • 125,304
  • 15
  • 256
  • 359
9

I wrote a kth out function:

function kth = kthout(k, ffnc, varargin)
% kthout: take the kth varargout from a func call %FOLDUP
%
% kth = kthout(k, ffnc, varargin)
%
% input:
%  k                      which varargout to get
%  ffnc                   function to call;
%  varargin               passed to ffnc;
% output:
%  kth                    the kth argout;

[outargs{1:k}] = feval(ffnc, varargin{:});
kth = outargs{k};

end %function

You can then call

val_i_want = kthout(3, @myfunc, func_input_1, func_input_2);

You could also wrap up the function like:

func_i_want = @(varargin)(kthout(3, @myfunc,varargin{:}));  % Assuming you want the third output.

After which you use

val_i_want = func_i_want(func_input_1, func_input_2);

Note that there is overhead associated with using anonymous functions like this, and this is not something I would do in code that would be called thousands of times.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
shabbychef
  • 1,940
  • 3
  • 16
  • 28
4

In MATLAB 2010a, I found a neat way of doing what you are asking for.

It is simply to use the character "~" (without the quotes of course) as your dummy variable (as many as you want when returning multiple parameters). This also works for input parameters to functions if the functions are designed to handle missing data.

I don't know if this existed in previous versions, but I just came across it recently.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sam
  • 41
  • 1
1

You can make a function (or anonymous function) that only returns selected outputs, e.g.

select = @(a,b) a(b);

Then you can call your function like this:

select(func,2);
select(func,1:3);

Or you can assign the output to a variable:

output(1,2:4) = select(func,1:3);
Dave
  • 49
  • 4
0

I don't see any reason not to use ans(n). Like this:

size(rand([5 10 20 40]));

b = ans(2);

It gives b = 10, and this way would be compatible with all MATLAB versions. Note that size() here is just used to represent any function that has multiple return variables.

Furthermore, this works to get the second output argument when you don't know how many arguments there will be! Whereas, if you do this:

[~, b] = size(a);

Then b = 8000! (You need to end with ~, to catch more arguments!)

user1596274
  • 187
  • 1
  • 1
  • 9
  • This answer assumes the variable being returned is a vector, which was probably not what the OP meant. – Neil Traft Mar 26 '15 at 06:38
  • 1
    This makes no sense. `size(a)` and `[b,c]=size(a)` return different things. Functions in MATLAB change behaviour based on the number of output arguments. – Cris Luengo Dec 12 '18 at 16:14
  • I'm having a hard time understanding this answer. I don't know how this contributes to the quality of the answers here, let alone that this doesn't directly answer the original question. – rayryeng Jan 09 '19 at 03:26
  • It's 6 years later, and I no longer use Matlab. As far as I remember, the function "size()" was irrelevant – I just used it as a function that would return multiple arguments. The point is that I can simply call func() and then ans(n) to get the value of returned variable number n. This appeared to work well for certain situations and be backwards compatible. It may only work with certain functions of course, or variable types, whatever. That's as much as I can help 6 years later. – user1596274 Jan 09 '19 at 14:16