Using Parameters within a Procedure
This page describes how to use parameters within the body of a Maple procedure:
Required Parameters
Parameters with the seq Modifier
Parameters with the uneval or evaln Modifiers
Optional and Expected Parameters
Keyword Parameters
Special Sequences
The _params Sequence and _nparams
The _options Sequence and _noptions
The _rest Sequence and _nrest
The _passed Sequence and _npassed (formerly args and nargs)
For any class of parameter, the usual way to refer to it within the procedure is by its declared name.
For information on how to declare parameters, see Parameter Declarations.
Details
A required parameter is one for which an argument must have been passed if the parameter is used during the execution of the procedure. In other words, a failure to pass an argument for a required parameter only raises an exception if an attempt is made to use that parameter during the particular invocation of the procedure. For example, a procedure may decide, based on the value of its first required parameter, that it does not have to use the second required parameter.
If a required parameter for which no argument was passed is used, an exception similar to one of these is raised:
Error, invalid input: f uses a 1st argument, x, which is missing
or
Error, invalid input: f uses a 1st argument, x (of type numeric), which is missing
A required or optional parameter declared with the seq modifier always has a value. That value will be one of the following:
A sequence of values of the specified type (the argument to seq),
a single value of that type, or
if no arguments matched the type, either NULL (for a required parameter) or the specified default value (for an optional parameter).
To do anything with these values other than pass them on to another procedure, the parameter should be converted to a list, and the list used in the procedure. For example:
AddAndMax := proc( x::seq(numeric) ) local a; a := 0; for i in [x] do a := a + i end do; return a, max(x) end proc;
Without the brackets around x, this procedure produces unexpected results if called with a single floating point number. The for var in expr loop iterates over the operands of expr. If expr is a sequence of two or more numbers, it works as desired, but if expr is a single floating point number, the loop instead adds the mantissa and exponent of the number (the operands of the float). By enclosing x in a list, the loop always iterates over the arguments that matched x.
Conversely, in the call to max, a single value for x should remain as a single value, and multiple values should remain as an expression sequence (the elements of which become the arguments to max).
Parameters declared with uneval or evaln are used like any other. Because Maple uses single-level evaluation rules inside procedures, these do not evaluate any further than they did when the function call that invoked the procedure was evaluated. The eval function can be used to evaluate such parameters further.
Both optional and expected ordered parameters are declared with default values. Therefore, using the parameter within a procedure always yields a value. If an argument matched the parameter, the value of the parameter is the argument. Otherwise, the value of the parameter is the declared default value.
Like the ordered parameters, keyword parameters also have default values, so using the parameter always yields a value. Unlike the ordered parameters though, keyword parameters receive their values from arguments of the form keyword=value. The value of a keyword parameter is the value part of such an argument. It is not the entire argument.
Maple provides a number of special named expression sequences to make it easy to work with parameters in ways that would be awkward if they could only be referred to by name.
The special symbols _params and _nparams can be used within a procedure to refer to the current values of the positional and ordered parameters. The _params symbol refers to an expression sequence containing _nparams members, one corresponding to each such declared parameter. Note that for any given procedure, _nparams is a constant.
The _params sequence can only be used when immediately followed by an index enclosed in square brackets, i.e. _params[indexExpr]. It cannot be used in any other context. The indexExpr can evaluate to one of the following:
An integer, N, in the range 1 to _nparams or -(_nparams) to −1. Negative integers index _params from the end instead of the beginning. This yields the value of the Nth parameter (or the (_nparams+1+N)th when N is negative). If no argument was passed for the requested parameter, the value is NULL.
A range of such integers. This yields an expression sequence of values, with any NULL values omitted. A sequence of all the non-NULL positional and ordered parameter values can be obtained using _params[1.._nparams]. Note that this may produce less than _nparams values.
An unevaluated name of a parameter. The notation _params['parameterName'] is equivalent to just writing the parameterName, except in the case of a required positional parameter that has not been assigned. In that case, _params['parameterName'] yields NULL whereas just using parameterName raises an exception:
f := proc(a, b, c) a + b + c end proc:
f(2,3);
Error, invalid input: f uses a 3rd argument, c, which is missing
f := proc(a, b, c) if _params['c'] = NULL then a + b else a + b + c end if end proc:
5
f(2,3,4);
9
The reason that _params cannot be used other than in an indexed context is to avoid confusion. If any of the arguments were omitted, and there was no default value for the corresponding parameter (or the default value is NULL), then the sequence returned by _params would have fewer than _nparams members. This is because NULL values cannot persist inside an expression sequence in Maple. Thus, for example,
s := _params; # not allowed
p3 := s[3];
might yield a different result than:
p3 := _params[3];
By always forcing _params to be indexed directly, this source of subtle programming errors is eliminated. If desired, the effect of using _params in a non-indexed context can still be had by explicitly writing _params[1.._nparams].
Example: A procedure which, depending on the value of keyword parameter multiply, either multiplies or divides the last three positional arguments by the first argument.
f := proc(a, b, c, d, {multiply := true}) if multiply then _params[-3 .. -1]*a; else _params[-3 .. -1]/a; end if; end proc:
f(100,1,2,3);
100,200,300
f(100,1.,2.,3.,multiply=false);
0.01000000000,0.02000000000,0.03000000000
The special symbols _options and _noptions are to keyword parameters approximately what _params and _nparams are to positional and ordered parameters.
The _options symbol refers to an expression sequence containing _noptions members (one for each declared keyword parameter of the procedure). Each member of _options is an equation of the form keyword=value.
If a keyword parameter was declared with multiple spellings, the entry corresponding to that parameter in _options uses the first spelling.
Unlike _params, _options need not be used in an indexed context. Because _options returns a sequence of equations, even the member corresponding to an argument with a NULL value (or NULL default value) is non-NULL. It is an equation of the form keyword=NULL.
When _options is used in an indexed context, the index must evaluate to an integer, a range of integers in the range 1 to _noptions or -(_noptions) to −1, an unevaluated name of a keyword parameter, or a sequence of such names. Negative integers index _options from the end instead of the beginning.
Indexing with a sequence of keyword parameter names yields a sequence of keyword=value equations.
Note that the order of the equations in _options does not necessarily correspond to the order in which the keyword parameters were declared. Instead, the equations are in lexicographic order by keyword (the first spelling for keyword parameters with multiple spellings). This is the same order that the keyword parameters are printed in if the procedure is displayed by the print command.
Because of this, the numeric index of the _options entry corresponding to a particular keyword parameter can change if new keyword parameters are added to the procedure. Thus, when indexing _options, it is safest to use the _options['keywordParameterName'] form.
The following example uses _options to pass the keyword equations on to another procedure.
with(LinearAlgebra):
g := proc(a::integer, {density::float:=1.0, generator:=0..0.5}) RandomMatrix(a, _options); end proc:
g(2, density=0.75, generator=1..9);
8040
g(3, density=0.88);
0.4797462131964514990.4001402344444000560.0.0.0.4787534177171487990.2108806413131374960.4852963908803078490.139249109433524199
The next example indexes into _options to pass only specific keyword arguments to another procedure.
g := proc(a::integer, {density::float:=1.0, generator:=0..0.5, mult:=1.0}) mult * RandomMatrix(a, _options['density','generator']); end proc:
g(4, density=0.75, generator=1..9, mult=1/2*x);
4⁢x0x9⁢x23⁢x203⁢x200x29⁢x27⁢x27⁢x24⁢x2⁢x3⁢x2
When there are more arguments in a function call than needed to match the called procedure's parameters, the remaining arguments are made available inside the procedure via _rest. The symbol _nrest gives the number of members of this sequence.
Because these extra arguments do not correspond to any declared parameters, it is not possible for such an argument to have a NULL value. Recall that the only way for a parameter to be NULL is for no argument to have matched the parameter, and if that parameter had a declared default value, that value was NULL. Since there is no declared parameter corresponding to any value in _rest, these conditions cannot hold.
Example: A procedure to return the number of entries in a sequence of numbers, together with the maximum and optionally (depending on the value of keyword parameter returnMean) the mean.
maxmean := proc ({returnMean := false}) if returnMean then _nrest, max(_rest), Statistics:-Mean([_rest]); else _nrest, max(_rest); end if; end proc:
c := maxmean(6,200,400,returnMean=true);
c≔3,400,202.
The special symbol _passed contains an expression sequence of the actual arguments that were passed to the procedure, without regard to how these arguments were matched to parameters. The number of members in _passed is given by _npassed.
Prior to Maple 10, _passed and _npassed were called args and nargs. For backward compatibility, these names will continue to work as synonyms for the new names.
The _passed sequence can be used to do explicit argument processing within the body of the procedure, although this is discouraged for two reasons:
Most argument processing requirements can now be handled using the mechanisms described so far in this document. Doing so is usually significantly faster (in terms of both execution time and development time) than doing it using hand-written argument processing algorithms within the procedure.
When special argument processing requirements do arise, it is often easier to work with _params, _options, and _rest. In many cases, the provided mechanisms can handle most of the processing, and it is only necessary to look at _rest to handle additional arguments.
Example: A procedure to find the maximum of an arbitrary sequence of numbers could be written as follows.
maximum := proc () local max, i; max := _passed[1]; for i from 2 to _npassed do if _passed[i] > max then max := _passed[i] end if end do; max; end proc:
A Note About Sequences
Care must be taken when the last three sequences described above (_options, _rest, and _passed) are of length one. In Maple, if an expression sequence consisting of a single element is assigned to a variable (for example my_opts := _options;), the variable will be set to that single element rather than to the expression sequence consisting solely of that element. The safest way to use expression sequences - though not the most efficient - is to turn them into lists as soon as possible (for example my_opts := [_options];).
These two examples illustrating possible issues when dealing with expression sequences of length one.
f := proc() local x; for x in _passed do print(x) end do; end proc:
f(m, n);
m
n
f(m+n);
m+n
g := proc() local my_passed, x; my_passed := _passed; for x in my_passed do print(x) end do; end proc:
g(m, n);
g(m+n);
For more information on parameters, see
1. Parameter Declarations
2. Parameter Modifiers
3. Using Parameters in Procedures
4. Argument Processing
See Also
Procedure Parameters
Procedures
Download Help Document