# HG changeset patch # User John W. Eaton # Date 1705691187 18000 # Node ID 56995fce2adc611c6e0a2a7e5a0d425457c72999 # Parent e96e2f9f9f37db6378ec603c8e682459f654f1be 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. diff -r e96e2f9f9f37 -r 56995fce2adc doc/interpreter/func.txi --- 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 diff -r e96e2f9f9f37 -r 56995fce2adc etc/NEWS.9.md --- 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 diff -r e96e2f9f9f37 -r 56995fce2adc libinterp/corefcn/stack-frame.h --- 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, diff -r e96e2f9f9f37 -r 56995fce2adc libinterp/octave-value/ov-usr-fcn.cc --- 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) diff -r e96e2f9f9f37 -r 56995fce2adc libinterp/op-kw-docs --- 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 diff -r e96e2f9f9f37 -r 56995fce2adc libinterp/parse-tree/pt-eval.cc --- 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 *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) diff -r e96e2f9f9f37 -r 56995fce2adc libinterp/parse-tree/pt-eval.h --- 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; diff -r e96e2f9f9f37 -r 56995fce2adc scripts/miscellaneous/nthargout.m --- 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)