Using Parameters within a Procedure
•
|
For any class of parameter, the usual way to refer to it within the procedure is by its declared name.
|
|
Required Parameters
|
|
•
|
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
|
|
Error, invalid input: f uses a 1st argument, x (of type numeric), which is missing
|
|
Parameters with the seq Modifier
|
|
•
|
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 with the uneval or evaln Modifiers
|
|
•
|
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.
|
|
|
|
Optional and Expected Parameters
|
|
•
|
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.
|
|
|
Keyword Parameters
|
|
•
|
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.
|
|
|
Special Sequences
|
|
•
|
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 _params Sequence and _nparams
|
|
•
|
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 to _nparams or -(_nparams) to . 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 := proc(a, b, c)
if _params['c'] = NULL then
a + b
else
a + b + c
end if
end proc:
|
| (1) |
| (2) |
•
|
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
|
|
might yield a different result than:
|
•
|
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:
|
| (3) |
>
|
f(100,1.,2.,3.,multiply=false);
|
| (4) |
|
|
The _options Sequence and _noptions
|
|
•
|
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 to _noptions or -(_noptions) to , or an unevaluated name (or sequence of names) of a keyword parameters. 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.
|
>
|
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);
|
| (5) |
| (6) |
•
|
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);
|
| (7) |
|
|
The _rest Sequence and _nrest
|
|
•
|
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);
|
| (8) |
|
|
The _passed Sequence and _npassed (formerly args and nargs)
|
|
•
|
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:
|
| (9) |
| (10) |
>
|
g := proc() local my_passed, x;
my_passed := _passed;
for x in my_passed do print(x) end do;
end proc:
|
| (11) |
| (12) |
|
|
|
Details
|
|
|
For further information on parameters, see
|
|
3. Using Parameters in Procedures
|
|
|