changeset 13749:62d1f56b0be7

New nthargout function * nthargout.m: New function. * func.txi (Multiple Return Values): document nthargout. * module.mk (general_FCN_FILES): Add nthargout.m * help.cc (varargin, varargout): Cross-reference other arg functions. * ov-user-fucn.cc (nargin, nargout, isargout): Ditto. * NEWS (3.6): Mention this new file.
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Tue, 25 Oct 2011 09:46:38 -0700
parents 77857d6fe074
children 5f71ab377898 be7ff59cbc7a
files NEWS doc/interpreter/func.txi scripts/general/module.mk scripts/general/nthargout.m src/help.cc src/ov-usr-fcn.cc
diffstat 6 files changed, 126 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Oct 24 18:06:04 2011 -0700
+++ b/NEWS	Tue Oct 25 09:46:38 2011 -0700
@@ -62,6 +62,7 @@
 
  ** Other miscellaneous new functions:
 
+      nthargout
       iscolumn
       issrow
       zscore
--- a/doc/interpreter/func.txi	Mon Oct 24 18:06:04 2011 -0700
+++ b/doc/interpreter/func.txi	Tue Oct 25 09:46:38 2011 -0700
@@ -289,6 +289,12 @@
 dimensions, and it is often desirable to give the individual return
 values distinct names.
 
+It is possible to use the @code{nthargout} function to obtain only some
+of the return values or several at once in a cell array. @ref{Cell Array
+Objects}
+
+@DOCSTRING(nthargout)
+
 In addition to setting @code{nargin} each time a function is called,
 Octave also automatically initializes @code{nargout} to the number of
 values that are expected to be returned.  This allows you to write
--- a/scripts/general/module.mk	Mon Oct 24 18:06:04 2011 -0700
+++ b/scripts/general/module.mk	Tue Oct 25 09:46:38 2011 -0700
@@ -54,6 +54,7 @@
   general/logspace.m \
   general/nargchk.m \
   general/nargoutchk.m \
+  general/nthargout.m \
   general/nextpow2.m \
   general/num2str.m \
   general/pol2cart.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/nthargout.m	Tue Oct 25 09:46:38 2011 -0700
@@ -0,0 +1,113 @@
+## Copyright (C) 2011 Jordi GutiƩrrez Hermoso
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} nthargout (@var{n}, @var{func}, @dots{})
+## @deftypefnx {Function File} {} nthargout (@var{n}, @var{ntot}, @var{func}, @dots{})
+## Return the @var{n}th output argument of function given by the
+## function handle or string @var{func}. Any arguments after @var{func}
+## are passed to @var{func}. The total number of arguments to call
+## @var{func} with can be passed in @var{ntot}; by default @var{ntot}
+## is @var{n}. The input @var{n} can also be a vector of indices of the
+## output, in which case the output will be a cell array of the
+## requested output arguments.
+##
+## The intended use @code{nthargout} is to avoid intermediate variables.
+## For example, when finding the indices of the maximum entry of a
+## matrix, the following two compositions of nthargout
+##
+## @example
+## @group
+## @var{m} = magic (5);
+## cell2mat (nthargout ([1, 2], @@ind2sub, size(@var{m}),
+##                      nthargout (2, @@max, @var{m}(:))))
+## @result{} 5   3
+## @end group
+## @end example
+##
+## @noindent
+## are completely equivalent to the following lines:
+##
+## @example
+## @group
+## @var{m} = magic(5);
+## [~, idx] = max (@var{M}(:));
+## [i, j] = ind2sub (size (@var{m}), idx);
+## [i, j]
+## @result{} 5   3
+## @end group
+## @end example
+##
+## It can also be helpful to have all output arguments in a single cell
+## in the following manner:
+##
+## @example
+## @var{USV} = nthargout ([1:3], @@svd, hilb (5));
+## @end example
+##
+## @seealso{nargin, nargout, varargin, varargout, isargout}
+## @end deftypefn
+
+## Author: Jordi GutiƩrrez Hermoso
+
+function out = nthargout (n, varargin)
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (isa (varargin{1}, "function_handle") || ischar (varargin{1}))
+    ntot = max (n(:));
+    func = varargin{1};
+    args = varargin(2:end);
+  elseif (isnumeric (varargin{1})
+          && (isa (varargin{2}, "function_handle") || ischar (varargin{2})))
+    ntot = varargin{1};
+    func = varargin{2};
+    args = varargin(3:end);
+  else
+    print_usage ();
+  endif
+
+  if (any (n != fix (n))  || ntot != fix (ntot) || any (n <= 0) || ntot <= 0)
+    error ("nthargout: N and NTOT must consist of positive integers")
+  endif
+
+  outargs = cell (1, ntot);
+
+  try
+    [outargs{:}] = feval (func, args{:});
+    if (numel (n) > 1)
+      out = outargs(n);
+    else
+      out = outargs{n};
+    endif
+  catch
+    err = lasterr ();
+    if (strfind ("some elements undefined in return list", err))
+      error ("nthargout: Too many output arguments: %d", ntot);
+    else
+      error (err);
+    endif
+  end_try_catch
+
+endfunction
+
+%!shared m
+%! m = magic (5);
+%!assert (nthargout ([1, 2], @ind2sub, size(m), nthargout (2, @max, m(:))), {5,3}) 
+%!assert (nthargout (3, @find, m(m>20)), [23, 24, 25, 21, 22]')
--- a/src/help.cc	Mon Oct 24 18:06:04 2011 -0700
+++ b/src/help.cc	Tue Oct 25 09:46:38 2011 -0700
@@ -729,14 +729,14 @@
     "-*- texinfo -*-\n\
 @deftypefn {Keyword} {} varargin\n\
 Pass an arbitrary number of arguments into a function.\n\
-@seealso{varargout, nargin, nargout}\n\
+@seealso{varargout, nargin, isargout, nargout, nthargout}\n\
 @end deftypefn"),
 
   pair_type ("varargout",
     "-*- texinfo -*-\n\
 @deftypefn {Keyword} {} varargout\n\
 Pass an arbitrary number of arguments out of a function.\n\
-@seealso{varargin, nargin, nargout}\n\
+@seealso{varargin, nargin, isargout, nargout, nthargout}\n\
 @end deftypefn"),
 
   pair_type ("while",
--- a/src/ov-usr-fcn.cc	Mon Oct 24 18:06:04 2011 -0700
+++ b/src/ov-usr-fcn.cc	Tue Oct 25 09:46:38 2011 -0700
@@ -635,7 +635,7 @@
 Octave.  If called with the optional argument @var{fcn_name}, return the\n\
 maximum number of arguments the named function can accept, or -1 if the\n\
 function accepts a variable number of arguments.\n\
-@seealso{nargout, varargin, varargout}\n\
+@seealso{nargout, varargin, isargout, varargout, nthargout}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -709,7 +709,7 @@
 @code{f}.\n\
 \n\
 At the top level, @code{nargout} is undefined.\n\
-@seealso{nargin, isargout, varargin, varargout}\n\
+@seealso{nargin, varargin, isargout, varargout, nthargout}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -806,7 +806,7 @@
 false.  @var{k} can also be an array, in which case the function works\n\
 element-by-element and a logical array is returned.  At the top level,\n\
 @code{isargout} returns an error.\n\
-@seealso{nargout, nargin, varargin, varargout}\n\
+@seealso{nargout, nargin, varargin, varargout, nthargout}\n\
 @end deftypefn")
 {
   octave_value retval;