changeset 32783:56995fce2adc stable

prepare for eventual removal of isargout * ov-usr-fcn.cc (val_in_table): Delete. (isargout1): Simplify. (Fisargout): Always return true for all values of k in the range 1:min (1, nargout). Update doc string. Update tests. * pt-eval.h, pt-eval.cc (tree_evaluator::ignored_fcn_outputs): Deprecate. Always return an empty Matrix object. (tree_evaluator::bind_auto_fcn_vars): Eliminate ignored_outputs argument. (tree_evaluator::execute_user_function): Don't call ignored_fcn_outputs or pass resulting value to bind_auto_fcn_vars. * stack-frame.h (stack_frame::IGNORED): Delete enum value. * func.txi: Remove discussion of isargout. * NEWS.9.md: Note change in isargout behavior. * op-kw-docs, nthargout.m: Remove isargout from @seealso list.
author John W. Eaton <jwe@octave.org>
date Fri, 19 Jan 2024 14:06:27 -0500
parents e96e2f9f9f37
children ac661cacb725 c6ef7981b6f1
files doc/interpreter/func.txi etc/NEWS.9.md libinterp/corefcn/stack-frame.h libinterp/octave-value/ov-usr-fcn.cc libinterp/op-kw-docs libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h scripts/miscellaneous/nthargout.m
diffstat 8 files changed, 66 insertions(+), 153 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/func.txi	Fri Jan 19 08:41:49 2024 -0500
+++ b/doc/interpreter/func.txi	Fri Jan 19 14:06:27 2024 -0500
@@ -628,25 +628,6 @@
 @end group
 @end example
 
-Functions may take advantage of ignored outputs to reduce the number of
-calculations performed.  To do so, use the @code{isargout} function to query
-whether the output argument is wanted.  For example:
-
-@example
-@group
-function [out1, out2] = long_function (x, y, z)
-  if (isargout (1))
-    ## Long calculation
-    @dots{}
-    out1 = result;
-  endif
-  @dots{}
-endfunction
-@end group
-@end example
-
-@DOCSTRING(isargout)
-
 @node Default Arguments
 @section Default Arguments
 @cindex default arguments
--- a/etc/NEWS.9.md	Fri Jan 19 08:41:49 2024 -0500
+++ b/etc/NEWS.9.md	Fri Jan 19 14:06:27 2024 -0500
@@ -173,6 +173,9 @@
 
         Function               | Replacement
         -----------------------|------------------
+        isargout               | none (see below)
+
+    * The implementation of `isargout` has been the source of a number of bugs and was inefficient, even for functions that did not use it.  It may be removed in a future version of Octave.  Until then, `isargout(k)` will return true for k in the range `1:min (1, nargout)`.
 
 - Properties
 
--- a/libinterp/corefcn/stack-frame.h	Fri Jan 19 08:41:49 2024 -0500
+++ b/libinterp/corefcn/stack-frame.h	Fri Jan 19 14:06:27 2024 -0500
@@ -130,7 +130,6 @@
   enum auto_var_type
   {
     ARG_NAMES,
-    IGNORED,
     NARGIN,
     NARGOUT,
     SAVED_WARNING_STATES,
--- a/libinterp/octave-value/ov-usr-fcn.cc	Fri Jan 19 08:41:49 2024 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Fri Jan 19 14:06:27 2024 -0500
@@ -790,7 +790,7 @@
 
 Programming Note.  @code{nargout} does not work for built-in functions and
 returns -1 for all anonymous functions.
-@seealso{nargin, varargout, isargout, nthargout}
+@seealso{nargin, varargout, nthargout}
 @end deftypefn */)
 {
   int nargin = args.length ();
@@ -886,39 +886,27 @@
 }
 
 static bool
-val_in_table (const Matrix& table, double val)
-{
-  if (table.isempty ())
-    return false;
-
-  octave_idx_type i = table.lookup (val, ASCENDING);
-  return (i > 0 && table(i-1) == val);
-}
-
-static bool
-isargout1 (int nargout, const Matrix& ignored, double k)
+isargout1 (int nargout, double k)
 {
   if (k != math::fix (k) || k <= 0)
     error ("isargout: K must be a positive integer");
 
-  return (k == 1 || k <= nargout) && ! val_in_table (ignored, k);
+  return k == 1 || k <= nargout;
 }
 
+// LEGACY FUNCTION as of Octave 9.
+
 DEFMETHOD (isargout, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn {} {@var{tf} =} isargout (@var{k})
-Within a function, return a logical value indicating whether the argument
-@var{k} will be assigned to a variable on output.
+This function is obsolete and may be removed from a future version of
+Octave.  Inside a function and now always returns true for @var{k} in
+the range @code{1:min (1, nargout)}.
 
-If the result is false, the argument has been ignored during the function
-call through the use of the tilde (~) special output argument.  Functions
-can use @code{isargout} to avoid performing unnecessary calculations for
-outputs which are unwanted.
+@var{k} can also be an array, in which case the function works
+element-by-element and a logical array is returned.
 
-If @var{k} is outside the range @code{1:max (nargout)}, the function returns
-false.  @var{k} can also be an array, in which case the function works
-element-by-element and a logical array is returned.  At the top level,
-@code{isargout} returns an error.
+At the top level, @code{isargout} returns an error.
 @seealso{nargout, varargout, nthargout}
 @end deftypefn */)
 {
@@ -937,16 +925,11 @@
   if (tmp.is_defined ())
     nargout1 = tmp.int_value ();
 
-  Matrix ignored;
-  tmp = tw.get_auto_fcn_var (stack_frame::IGNORED);
-  if (tmp.is_defined ())
-    ignored = tmp.matrix_value ();
-
   if (args(0).is_scalar_type ())
     {
       double k = args(0).double_value ();
 
-      return ovl (isargout1 (nargout1, ignored, k));
+      return ovl (isargout1 (nargout1, k));
     }
   else if (args(0).isnumeric ())
     {
@@ -954,7 +937,7 @@
 
       boolNDArray r (ka.dims ());
       for (octave_idx_type i = 0; i < ka.numel (); i++)
-        r(i) = isargout1 (nargout1, ignored, ka(i));
+        r(i) = isargout1 (nargout1, ka(i));
 
       return ovl (r);
     }
@@ -966,72 +949,50 @@
 
 /*
 %!function [x, y] = try_isargout ()
-%!  if (isargout (1))
-%!    if (isargout (2))
-%!      x = 1; y = 2;
-%!    else
-%!      x = -1;
-%!    endif
-%!  else
-%!    if (isargout (2))
-%!      y = -2;
-%!    else
-%!      error ("no outputs requested");
-%!    endif
-%!  endif
-%!endfunction
-%!
-%!function [a, b] = try_isargout2 (x, y)
-%!  a = y;
-%!  b = {isargout(1), isargout(2), x};
+%!  global isargout_global
+%!  isargout_global = [isargout(1), isargout(2)];
+%!  x = 1;
+%!  y = 2;
 %!endfunction
 %!
 %!test
-%! [x, y] = try_isargout ();
-%! assert ([x, y], [1, 2]);
-%!
-%!test
-%! [x, ~] = try_isargout ();
-%! assert (x, -1);
+%! global isargout_global
+%! unwind_protect
+%!   [x, y] = try_isargout ();
+%!   assert ([x, y], [1, 2]);
+%!   assert (isargout_global, [true, true]);
+%! unwind_protect_cleanup
+%!   clear -global isargout_global
+%! end_unwind_protect
 %!
 %!test
-%! [~, y] = try_isargout ();
-%! assert (y, -2);
-%!
-%!error [~, ~] = try_isargout ()
+%! global isargout_global
+%! unwind_protect
+%!   [x, ~] = try_isargout ();
+%!   assert (x, 1);
+%!   assert (isargout_global, [true, true]);
+%! unwind_protect_cleanup
+%!   clear -global isargout_global
+%! end_unwind_protect
 %!
-## Check to see that isargout isn't sticky:
-%!test
-%! [x, y] = try_isargout ();
-%! assert ([x, y], [1, 2]);
-%!
-## It should work without ():
-%!test
-%! [~, y] = try_isargout;
-%! assert (y, -2);
-%!
-## It should work in function handles, anonymous functions, and cell
-## arrays of handles or anonymous functions.
 %!test
-%! fh = @try_isargout;
-%! af = @() try_isargout;
-%! c = {fh, af};
-%! [~, y] = fh ();
-%! assert (y, -2);
-%! [~, y] = af ();
-%! assert (y, -2);
-%! [~, y] = c{1}();
-%! assert (y, -2);
-%! [~, y] = c{2}();
-%! assert (y, -2);
+%! global isargout_global
+%! unwind_protect
+%!   [~, y] = try_isargout ();
+%!   assert (y, 2);
+%!   assert (isargout_global, [true, true]);
+%! unwind_protect_cleanup
+%!   clear -global isargout_global
+%! end_unwind_protect
 %!
-## Nesting, anyone?
 %!test
-%! [~, b] = try_isargout2 (try_isargout, rand);
-%! assert (b, {0, 1, -1});
-%!test
-%! [~, b] = try_isargout2 ({try_isargout, try_isargout}, rand);
-%! assert (b, {0, 1, {-1, -1}});
+%! global isargout_global
+%! unwind_protect
+%!   [~, ~] = try_isargout ()
+%!   assert (isargout_global, [true, true]);
+%! unwind_protect_cleanup
+%!   clear -global isargout_global
+%! end_unwind_protect
 */
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/op-kw-docs	Fri Jan 19 08:41:49 2024 -0500
+++ b/libinterp/op-kw-docs	Fri Jan 19 14:06:27 2024 -0500
@@ -873,14 +873,14 @@
 -*- texinfo -*-
 @deftypefn {} {} varargin
 Pass an arbitrary number of arguments into a function.
-@seealso{varargout, nargin, isargout, nargout, nthargout}
+@seealso{varargout, nargin, nargout, nthargout}
 @end deftypefn
 varargout
 @c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} varargout
 Pass an arbitrary number of arguments out of a function.
-@seealso{varargin, nargin, isargout, nargout, nthargout}
+@seealso{varargin, nargin, nargout, nthargout}
 @end deftypefn
 while
 @c libinterp/parse-tree/oct-parse.yy
--- a/libinterp/parse-tree/pt-eval.cc	Fri Jan 19 08:41:49 2024 -0500
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Jan 19 14:06:27 2024 -0500
@@ -1451,40 +1451,6 @@
   m_debug_frame = m_call_stack.dbupdown (n, verbose);
 }
 
-Matrix
-tree_evaluator::ignored_fcn_outputs () const
-{
-  Matrix retval;
-
-  const std::list<octave_lvalue> *lvalues = m_lvalue_list;
-
-  if (! lvalues)
-    return retval;
-
-  octave_idx_type nbh = 0;
-
-  for (const auto& lval : *lvalues)
-    nbh += lval.is_black_hole ();
-
-  if (nbh > 0)
-    {
-      retval.resize (1, nbh);
-
-      octave_idx_type k = 0;
-      octave_idx_type l = 0;
-
-      for (const auto& lval : *lvalues)
-        {
-          if (lval.is_black_hole ())
-            retval(l++) = k+1;
-
-          k += lval.numel ();
-        }
-    }
-
-  return retval;
-}
-
 // If NAME is an operator (like "+", "-", ...), convert it to the
 // corresponding function name ("plus", "minus", ...).
 
@@ -3553,9 +3519,6 @@
 
   octave_value_list args (xargs);
 
-  // FIXME: this probably shouldn't be a double-precision matrix.
-  Matrix ignored_outputs = ignored_fcn_outputs ();
-
   octave_value_list ret_args;
 
   int nargin = args.length ();
@@ -3618,8 +3581,8 @@
         }
     }
 
-  bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin,
-                      nargout, user_function.takes_varargs (),
+  bind_auto_fcn_vars (xargs.name_tags (), nargin, nargout,
+                      user_function.takes_varargs (),
                       user_function.all_va_args (args));
 
   // For classdef constructor, pre-populate the output arguments
@@ -5219,13 +5182,11 @@
 
 void
 tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names,
-                                    const Matrix& ignored_outputs,
                                     int nargin, int nargout,
                                     bool takes_varargs,
                                     const octave_value_list& va_args)
 {
   set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names));
-  set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs);
   set_auto_fcn_var (stack_frame::NARGIN, nargin);
   set_auto_fcn_var (stack_frame::NARGOUT, nargout);
   set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ());
@@ -5548,4 +5509,12 @@
 %!error echo ("on", "all", "all")
 */
 
+// DEPRECATED in Octave 9.
+
+Matrix
+tree_evaluator::ignored_fcn_outputs () const
+{
+  return Matrix ();
+}
+
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-eval.h	Fri Jan 19 08:41:49 2024 -0500
+++ b/libinterp/parse-tree/pt-eval.h	Fri Jan 19 14:06:27 2024 -0500
@@ -344,6 +344,7 @@
     SC_OTHER      // command-line input or eval string
   };
 
+  OCTAVE_DEPRECATED (9, "tree_evaluator::ignored_fcn_outputs is obsolete and now always returns an empty Matrix object");
   Matrix ignored_fcn_outputs () const;
 
   octave_value make_fcn_handle (const std::string& nm);
@@ -886,8 +887,7 @@
   bool quit_loop_now ();
 
   void bind_auto_fcn_vars (const string_vector& arg_names,
-                           const Matrix& ignored_outputs, int nargin,
-                           int nargout, bool takes_varargs,
+                           int nargin, int nargout, bool takes_varargs,
                            const octave_value_list& va_args);
 
   std::string check_autoload_file (const std::string& nm) const;
--- a/scripts/miscellaneous/nthargout.m	Fri Jan 19 08:41:49 2024 -0500
+++ b/scripts/miscellaneous/nthargout.m	Fri Jan 19 14:06:27 2024 -0500
@@ -68,7 +68,7 @@
 ## @var{USV} = nthargout ([1:3], @@svd, hilb (5));
 ## @end example
 ##
-## @seealso{nargin, nargout, varargin, varargout, isargout}
+## @seealso{nargin, nargout, varargin, varargout}
 ## @end deftypefn
 
 function arg = nthargout (n, varargin)