The use Statement
|
Calling Sequence
|
|
use <expseq> in <statseq> end use
|
|
Parameters
|
|
expseq
|
-
|
expression sequence of bindings
|
statseq
|
-
|
statement sequence
|
|
|
|
|
Description
|
|
•
|
The use statement allows you to specify local bindings of names, module "imports," and operator overriding.
|
|
Syntax
|
|
•
|
The syntax of the use statement consists of two parts. The first is an expression sequence <expseq> of binding forms (described below). The second is the body, which is simply a sequence of Maple statements <statseq>. The two parts are enclosed and separated by several keywords. The use statement begins with the keyword use, and is terminated (after the body) by the keyword combination end use. The sequence of binding forms is separated from the body by the keyword in.
|
|
Note: In both 1-D and 2-D math notation, statements entered between the use and end use keywords must be terminated with a colon (:) or semicolon (;).
|
•
|
The <expseq> part of the use statement is an expression sequence of one or more bindings forms. A binding form may take one of several forms.
|
|
The simplest kind of binding form is an equation whose left-hand side is a name. The right-hand side of the equation may be any Maple expression, but not an expression sequence. Other kinds of binding forms are defined in terms of equational binding forms.
|
|
Module member selection expressions can also appear as binding forms. A binding of the form m:-e is equivalent to the equational binding form e=m:-e .
|
|
Finally, a module expression (or the name of a module expression) can be used as a binding form. Using a module m as a binding form is equivalent to specifying the equation e=m:-e for all exports e of m.
|
|
|
Semantics
|
|
•
|
The use statement differs from all other Maple statements in that it is resolved during automatic simplification, rather than during evaluation. You cannot evaluate a use statement.
|
•
|
The use statement causes a syntactic transform of its body, according to the substitutions specified in the sequence of binding forms. It is unlike simple substitution, however, in that it behaves properly with respect to the static scoping rules of the Maple language.
|
•
|
Each use statement introduces a new binding contour, within which the names on the left-hand side of each of the binding equations are replaced, during simplification, by the corresponding values on the right-hand sides of the binding equations. The body of the use statement is rewritten, replacing each occurrence of each name that occurs in the bindings by the corresponding expression on the right-hand side of the binding equation. See Example 1 and Example 11.
|
|
Note: Each occurrence of a bound name is replaced by the corresponding expression throughout the body of the use statement. When the body of the use statement is evaluated, the value of the bound name will be evaluated once for each occurrence of the name. This means that while the use statement itself imposes no performance penalty whatsoever during evaluation, care must be exercised when the right-hand sides of bindings may perform expensive computations. The right-hand sides of the binding forms are not evaluated when processing the use statement.
|
•
|
You cannot define mutually recursive procedures with the use statement.
|
•
|
When one use statement occurs within another, any bindings introduced by the inner use statement that conflict with bindings specified in the enclosing use statement take precedence. In other words, re-binding a name in an inner use statement causes the outer binding to be shadowed by the inner binding. After the inner use statement has been resolved, the outer binding again becomes visible. See Example 2 and Example 10.
|
•
|
It is possible (and not unreasonable) to write a use statement in which there is a binding conflict. This can happen easily when two modules are bound in the same use statement and happen to both export a symbol with a given name. This is equivalent to specifying two binding equations with the same left-hand side. When this occurs, the first binding equation is taken to resolve the conflict. Thus, if two modules m1 and m2 export e, then occurrences of the symbol e in the body of a use statement binding both m1 and m2 will be bound to m1:-e if the modules are bound in the order m1, m2 and to m2:-e if they are bound in the order m2, m1. See Example 12.
|
•
|
An additional feature of the use statement is that it affords the possibility of (locally) overriding the meaning of infix binary operators. When the left-hand side of a binding equation is the name of a standard infix binary operator (such as `+` or `*`), or of a unary prefix or postfix operator, expressions involving the operator are rewritten so that the operator expression is replaced by a function expression in which the called expression (normally, a procedure or name) is the value to which the operator name is bound in the use statement. This is also done automatically when a module is used in the binding sequence, if any of its exports have an infix operator name. See Examples 5, 6, 7, and 8.
|
•
|
The operator names that can be rebound are `@`, `@@`, `%`, `%%`, `%%%`, `.`, `+`, `*`, `-`, `/`, `mod`, `^`, `!`, `union`, `minus`, `intersect`, `subset`, `in`, `$`, `and`, `or`, `not`, `xor`, `implies`, `=`, `<>`, `<`, `<=`, `assuming`, `<|>`, `<,>`, `[]`, `{}`, `?()`, `?[]`, and `~`. Indeed, the only operator names that cannot be rebound are `||`, `:-`, `::`, `..`, `,`, `->`, and `:=`. `>` and `>=` can be rebound, but not independently of `<` and `<=`, respectively. All elementwise operators are processed through ~.
|
|
Note: `!` is a unary postfix operator, while `not` (logical negation), `-` (arithmetic negation), and `/` (inversion) are used strictly as unary prefix operators.
|
|
`[]` and `{}` refer to list and set constructors. `?()` refers to function invocation and `?[]` refers to indexing. `?()` maps FName(arg1,arg2) to `?()`(FName,[arg1,arg2]) and `?[]` maps TName[arg1,arg2] to `?[]`(TName,[arg1,arg2]).
|
|
An overloaded tableref, `?[]`, is the only overloadable operator that can appear on the left side of the assignment operator, :=. The expression TName[arg1,arg2] := val is automatically changed to `?[]`(TName,[arg1,arg2],[val]). In the case where TName is an expression sequence, ie. (TName1,TName2)[index], you will need to use args[-1] and args[-2] to safely refer to the value and index parameters, and args[1..-3] to find TName. Assignment overloading only works with :=, and not the assign command. It is invalid to have an overloaded tableref along with other variables on the left side of := as part of a multiple assignment expression. See overload for an example of index overloading.
|
|
Sequences on the left side of `=`, `<>`, `<`, and `<=` will cause procname to be called with an index, whose value indicates how many of the operands are from the left hand side of the original operator invocation. For example, (1,2)=(3,4) would be ambiguous if called as F(1,2,3,4). Instead this call becomes F[2](1,2,3,4) indicating that the first two arguments are from the left hand side. When exactly one object appears on the left side of the operator, no index is used on procname.
|
|
|
|
Examples
|
|
|
Example 1
|
|
>
|
|
| (1) |
|
|
Example 2
|
|
>
|
|
| (2) |
|
|
Example 3
|
|
>
|
proc()
use a = 2, b = f() in
a + b
end use;
end proc;
|
| (3) |
|
Note that the use statement has been replaced by the rewritten body after the procedure has been simplified.
|
|
|
Example 4
|
|
|
No evaluation of the right-hand sides of binding forms occurs when the use statement is processed. Carelessness can lead to sources of inefficiency.
|
>
|
f := proc()
use t = proc() print(HELLO) end() in
t; t
end use;
end proc;
|
| (4) |
>
|
|
| (5) |
|
|
Example 5
|
|
>
|
|
| (6) |
|
|
Example 6
|
|
>
|
g := proc( a, b )
use
`+` = ( ( a, b ) -> a + b mod 5 ),
`*` = ( ( a, b ) -> a * b mod 5 ) in
a + a * b
end use
end proc;
|
| (7) |
>
|
|
| (8) |
|
|
Example 8
|
|
>
|
p := proc( a, b )
use `*` = Mul, `/` = Inv, `+` = Add, `-` = Neg in
a*b*(a + b)/(a - b)
end use
end proc;
|
| (10) |
|
|
Example 9
|
|
|
You cannot define procedures that call one another in a single use statement.
|
>
|
h := proc()
use a = proc( x ) 2 * b( x ) end proc, b = proc( x ) x - 1 end proc in
a( 2 )
end use
end proc;
|
| (11) |
>
|
|
| (12) |
|
To do something like this, instead write
|
>
|
h := proc()
use b = proc( x ) x - 1 end proc in
use a = proc( x ) 2 * b( x ) end in
a( 2 )
end use
end use
end proc;
|
| (13) |
>
|
|
| (14) |
|
The order of nesting in the preceding example is significant. Changing it breaks the desired behavior.
|
>
|
h := proc()
use a = proc( x ) 2 * b( x ) end proc in
use b = proc( x ) x - 1 end proc in
a( 2 )
end use
end use
end proc;
|
| (15) |
>
|
|
| (16) |
|
|
Example 10
|
|
|
Note the distinction between a single use statement and nested use statements.
|
>
|
f := proc()
use a = a + b, b = a - b in
a * b
end use
end proc;
|
| (17) |
>
|
g := proc()
use a = a + b in
use b = a - b in
a * b
end use
end use
end proc;
|
| (18) |
|
|
Example 11
|
|
|
It is important to recognize that the use statement is resolved during simplification. This can have some surprising consequences if one is not mindful of this and the use statement is entered at the top level.
|
>
|
|
| (19) |
>
|
|
| (20) |
>
|
|
| (21) |
|
This occurs because basic arithmetic is performed during automatic simplification in Maple, so the numeric result of the computation 2 * 1/100000000000000000000001.0 is computed before the evaluation phase that executes the preceding assignment statement. Thus, the original setting of Digits (the default, ) is in effect at the time the number is computed. To correct this behavior, enter exact numeric quantities and make an explicit call to evalf.
|
>
|
|
>
|
|
| (22) |
|
This forces the floating-point computation to be delayed until evaluation time, so that the assignment to Digits will already have taken place when the value is computed by evalf.
|
|
Note that when using 2-D math notation in the Standard interface, the expression is effectively rewritten as `*`(2,`/`(1,100000000000000000000001.)) which is not subject to early constant simplification.
|
|
|
Example 12
|
|
|
Binding conflicts are resolved by taking the first binding equation that binds a symbol.
|
>
|
|
| (23) |
>
|
|
| (24) |
|
Note how conflicts between exported names in module bindings are handled. The first module from which a name can be bound is used.
|
>
|
|
>
|
|
>
|
|
| (25) |
>
|
|
| (26) |
>
|
|
| (27) |
>
|
|
| (28) |
>
|
|
| (29) |
>
|
|
| (30) |
>
|
|
| (31) |
>
|
|
| (32) |
>
|
|
| (33) |
>
|
|
| (34) |
>
|
|
| (35) |
>
|
|
| (36) |
>
|
|
|
|
|