Loren on the Art of MATLAB

April 14th, 2009

Convenient nargout Behavior

Here's a question that was recently posed at MathWorks.

I'm trying to invoke a function handle. It either returns 0 or 1 output arguments. If it returns an output argument, I want to get it; if not I would like to just invoke the function and be on my way. I have no way of knowing ahead of time whether the function returns something or not.

 

This situation can arise when you are building an application in which you expect to work with user-supplied functions. You can solve this using try construct, but this situation arises frequently enough that we decided to introduce the nargout bump. So what happens?

Contents

nargout Bump from 0 to 1

Many MATLAB functions return 1 result even when called with an nargout is 0. For these, here's a technique that may be of interest. It allows for a bump in nargout on the left-hand side.

Let's assume the variable c is unitialized and then call a function f.

   [c{1:0}] = f(...);

f is called with nargout of 0, because 1:0 is an empty vector. If f returns no arguments, c is an empty cell. However, if f returns a result, c is a 1x1 cell containing that result.

Why does nargout Behave this Way?

Since this is not a widely known technique, I'll explain one more use of it. Suppose you are writing a function foo, and after some preparation you want foo to return all of the results, if any, of a call on bar, passing along to bar the number of arguments given to foo. The template looks like this.

   function varargout = foo(...)
     ... whatever ...
   [varargout{1:nargout}] = bar(...);

Anonymous functions use exactly this technique to pass along nargout to their body and to return that body's results as the result of the anonymous function. This requirement on anonymous functions, and the observation that a significant number of other functions work in the same way, is why we introduced the bump.

Will this Simplify Some Code?

I wonder if this information allows you to simplify some of your code. Please share your results here.


Get the MATLAB code

Published with MATLAB® 7.8

7 Responses to “Convenient nargout Behavior”

  1. Oliver Woodford replied on :

    Useful. It allowed me to change:

    str = sprintf('"%s" %s', xpdf_path, cmd);
    if nargout
        [varargout{:}] = system(str);
    else
        system(str);
    end
    

    to:

    [varargout{1:nargout}] = system(sprintf('"%s" %s', xpdf_path, cmd));
    

    Oliver

  2. Sung Soo replied on :

    I use similar technique to access subfunctions because I don’t want to have many small functions in different m-files though ‘class’ can solve this too.

  3. Kieran replied on :

    Thanks Loren. This code really helped me in using subsref in my classes. I wanted to only change some subsref functionality and call the builtin version for the rest, but ran into output argument issues. I ended up doing something like:

    function varargout = subsref(this, s)
    use_built_in = true;
    % Add custom subsref here and set use_built_in to false.

    % Use default subsref for others.
    if use_built_in
    [varargout{1:nargout}] = builtin(’subsref’, this, s);
    end
    end

  4. Loren replied on :

    I’m delighted that several of you find good use in this nargout behavior.

    –Loren

  5. OysterEngineer replied on :

    I understand that 1:0 is an empty matrix.

    But, by what is happening with [c{1:0}] = f(…)

    Is it really doing something like: [c{1:0}] = [] ?

    Also, what do you mean when you say, “when called with an nargout is zero . . . ?” The FRP is nicely clear in explaining that it can be called without an input argument to return the number of output arguments a user has supplied. Or, it can be called with a function handle or a function name as an input argument to return the number of output arguments the function was written to provide. So, which use are you referring to?

  6. Loren replied on :

    OysterEngineer-

    When MATLAB goes to calcualate [c{1:0}] = f(…),
    it is finding 0 elements on the left side (numel([c{1:0}]) IS 0) which IS nargout(f), and therefore f gets called as if nargout is 0.

    –Loren

  7. OysterEngineer replied on :

    That helps some. I see how the numel([c{1:0}0] is 0.

    But, I haven’t been able to invent a function, f, with no outputs such that nargout(’f') or nargout(@f)is also 0. I keep getting -1.

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Jun: I totally can not believe it, Loren. You are really helpful. Thank you so much, MATLAB master!
  • Loren: Wow folks- Always lots of interest when there’s a quickie to try out! I will only make 2 general...
  • Loren: Jun- ismember is your friend here: >> [aa,ind] = ismember(Array2,Arra y1) aa = 1 1 1 1 1 1 1 ind = 1 2 1 4 4 3...
  • Dan: I like the first way better than the second way. Combining the arrays into one and running any is nice, although...
  • James Myatt: How about I = (a == 0 | b == 0); a(I) = []; b(I) = [];
  • Tunc: Hello Loren, love your blog because of such inspiring and challenging comments to such ’small’...
  • Pekka Kumpulainen: Here is my tradeoff. I usually want to keep the original variables as they are most probably...
  • Iain: Followup: Of course, to allow NaNs (counting them as non-zero): mask = (a~=0) & (b~=0); The mask says “a...
  • Matt Fig: I would usually go with something like this: y = a&b; x = a(y); y = b(y); But I was surprised to find...
  • kk: c=all([a;b]) a(c) a(b)

These postings are the author's and don't necessarily represent the opinions of The MathWorks.