Contents Previous Next Index
5 Maple Statements
5.1 In This Chapter
Introduction
Expression Statements
Assignments
Flow Control
The use Statement
Other Statements
5.2 Introduction
A statement is a single complete piece of code that Maple can execute. There are many types of statements in Maple, including expression statements, assignment statements, selection statements (if ... then), repetition statements (loops), and program instructions (quit, save, read).
A statement differs from an expression in that it is normally evaluated for effect, rather than for its value. Most statements that do not consist of a single expression are formed so as to have a side effect.
5.3 Statement Separators
Statements in Maple must be terminated with a semicolon (;) or a colon (:).
Statements can be run in Maple one at a time, or multiple statements can be run on one line. If multiple statements are run on one line, the statements must be separated by a statement separator, either a semicolon (;) or a colon (:).
At the top level, the output of a statement that ends with a colon is hidden.
a:=2: a^2;
4
Note: In the standard interface, for input in 2-D math, the semicolon at the end of a statement can be omitted.
5.4 Expression Statements
The simplest kind of statement in Maple is the expression statement. It consists of an arbitrary expression, whose evaluation constitutes the effect of the statement.
Pi;
π
sin( Pi - x );
sin⁡x
int( sin( Pi - x ), x );
−cos⁡x
5.5 Assignments
Assignment statements allow you to associate a value or expression with a name. The assignment statement has the general form
lhs := rhs
Evaluating the assignment associates the value on the right-hand side of the assignment with the name on the left-hand side. After the assignment has taken effect, the result is the associated value when the assigned name is evaluated.
Here, the name a has no assigned value, so it evaluates to itself.
a;
a
The following assignment statement associates the value 2 / 3 with the name a.
a := 2 / 3;
a≔23
Subsequent evaluation of the name a results in the assigned value 2 / 3.
23
a + 1 / 3;
1
Associate the symbolic expression Pi / 2 with the name b by executing the following assignment statement.
b := Pi / 2;
b≔π2
Subsequently, the assigned value of b is used whenever the name b appears in an expression.
sin( b );
In this expression, the assigned value Pi / 2 of the name b is substituted to yield the expression sin( Pi / 2 ), and then the value of the procedure sin at this expression is computed, resulting in the overall value 1 for the expression.
Multiple Assignment
You can perform several assignments in a single statement, known as a multiple assignment. This has the general form
(lhs1, lhs2, ..., lhsN) := (rhs1, rhs2, ..., rhsN)
The parentheses on the right- and left-hand sides of the assignment are not required, but are considered good practice.
For example, the multiple assignment statement
(x, y, z) := ( sin( t ), cos( t ), tan( t ) );
x,y,z≔sin⁡t,cos⁡t,tan⁡t
establishes assigned values for all three names x, y, and z.
x;
sin⁡t
y;
cos⁡t
z;
tan⁡t
The number of components on each side of the assignment symbol := must be the same.
(a, b, c) := (2, 3);
Error, mismatched multiple assignment of 3 variables on the left side and 2 values on the right side
A common idiom is to use a multiple (double) assignment to swap the values of two variables without introducing an additional temporary variable.
(x, y) := (1, 2):
2
(x, y) := (y, x):
Note that using the swap idiom with unassigned names will lead to an infinite recursion.
(u, v) := (v, u);
u,v≔v,u
Evaluating u or v (full evaluation) produces an error. If you evaluate one level at a time using eval(u, i), you can see what happens.
u;
Error, too many levels of recursion
v;
seq( eval( u, i ), i = 1 .. 10 );
v,u,v,u,v,u,v,u,v,u
seq( eval( v, i ), i = 1 .. 10 );
u,v,u,v,u,v,u,v,u,v
Assignment Expressions
In addition to writing an assignment as a statement, an assignment can also appear almost anywhere that an expression can appear, including within another expression. This is known as an assignment expression or inline assignment.
An assignment used as or within an expression must always be enclosed in parentheses, even when the immediately surrounding context would already be a set of parentheses.
[(a := 1), (b := 2)];
1,2
a, b;
s := sin((t := Pi/3));
s≔32
s^2 + cos(t)^2;
The result of an inline assignment is the value that was assigned, that is, the evaluated right-hand side of the assignment. This value can then be used by the enclosing context.
An assignment within an expression takes place only when and if the part of the expression containing it is evaluated. This can be useful to reuse an expensive-to-compute value in computed in the middle of a complex condition.
f := unapply( int(1/(x^4+1),x), x ): x := 3.5; if x > 0 and (t := evalf(f(sqrt(x)))) > 0 and t < 1 then print(x,sqrt(t)) end if;
x≔3.5
Except in the case of logical operators, which follow left-to-right McCarthy (short-circuit) evaluation rules, it is generally not possible to predict the order in which the parts of an expression will be evaluated. Therefore, an assigned name should not be used elsewhere in the same expression with the expectation that the assignment has (or has not) taken place.
Inline assignment can be used to assign the same value to several variables in a single statement. Here is an assignment statement whose right-hand side consists of a pair of nested assignment expressions:
a := (b := (c := evalf(Pi,10)));
a≔3.141592654
L := ["one","two","three","infinity"]: for i from 1 to (last := numelems(L)) do # Print a separator before the last element of the list. if i = last then print(`...`) end if; print(i,L[i]) end do:
1,one
2,two
3,three
...
4,infinity
An inline assignment can often save duplication of code. For example, instead of writing,
line := readline("myfile.txt"); while line <> 0 do # process line ... line := readline("myfile.txt") end do;
one can write the more succinct and less error prone:
while (line := readline("myfile.txt")) <> 0 do # process line ... end do;
Operator Assignments
In addition to assigning an already computed value to a variable, it is possible to combine an operation and assignment into one using an operator assignment. These are:
+=
-=
*=
.=
/=
mod=
^=
,=
||=
intersect=
minus=
union=
and=
implies=
or=
xor=
Each of these performs the same operation that it would if the = were omitted, using the evaluated left and right hand sides of the assignment operator as its operands. The result is then assigned to the left hand side name.
The benefit of using an assignment operator is that the left hand side need only be resolved once. That is, the process of evaluating it to a name (which must be done before evaluating it to a value) is only done once. Thus, in an operator assignment such as A[veryBigExpression] += 1, the index veryBigExpression is only evaluated once. If the assignment were written as A[veryBigExpression] := A[veryBigExpression] + 1, then the index would be evaluated twice.
Like simple assignments (:=), an operator assignment can be used within an expression by enclosing it in parentheses. The result of such an embedded assignment is the computed value that was assigned to the left hand side.
The increment (+=) and decrement (-=) assignment operators each have an even shorter form that can be used when the right hand side is 1. The expression ++x is equivalent to x += 1, and --x is equivalent to x -= 1.
Unlike the longer forms, the short forms are expressions in their own right, and thus can be used within a larger expression without requiring extra parentheses (except where needed for disambiguation). The value of such an expression is the incremented or decremented value.
The short forms can also be written in postfix form (x++ and x--), in which case the effect on their argument, x, is the same, but the value of the expression is the original value of x.
If an operator assignment involving the same left hand side appears more than once in an expression, the order in which the assignments are carried out is undefined, so this should be avoided.
Special Semantics of the ,= Assignment Operator
In most cases, the operator assignment a ,= b is equivalent to a = a,b, forming an expression sequence from the values of a and b, and assigning it back to variable a.
In the special case where the value of the left hand side is a one dimensional Array, the Array is expanded and the right hand side appended to the Array in-place. If the right hand side is an expression sequence (e.g., a ,= b,c,d) each element of the sequence is appended separately.
If the left hand side is an Array with a hardware datatype, and a right hand side is a one dimensional Array, then the contents of that Array are appended to the left hand side.
If the left hand side is an Array with a datatype of integer[1] (i.e., an array of bytes), and a right hand side is a string, the byte values of the characters in the string are individually appended to the left hand side.
If the left hand side is an object that implements a `,=` method, then that method is invoked to perform the operation. For example, the MutableSet object implements this method such that ms ,= x is equivalent to insert(ms,x) or ms union= MutableSet(x).
In cases other than those above, a right hand side is appended in its entirety as an element of the left hand side.
If any of the assignments described above are not possible (e.g. the right hand side is a symbol and the array has datatype float[8]), an exception is raised.
5.6 Flow Control
A number of Maple statements are used to direct the flow of control in a program; that is, the sequence in which the various statements of the program are run.
Sequencing
The simplest form of a Maple program is a sequence of zero or more statements, separated either by semicolons or colons. A sequence of statements is run in the order in which they are entered.
For example, running these three statements
a := 2;
a≔2
b := 3;
b≔3
sin( a + b );
sin⁡5
executes the assignment to the name a, then the assignment to the name b is executed and, finally, the value of the expression sin( a + b ) is computed.
The flow of control in a Maple program consisting of a sequence of statements moves from one statement to the next, in order.
Many Maple statements are compound statements that contain statement sequences as constituents.
Branching
The simplest form of flow control is a branching, or if statement. Basically, an if statement has the syntax
if condition then
statseq
end if
in which condition is a Boolean-valued expression (that is, one which evaluates to one of the values true, FAIL, or false), and statseq is a (possibly empty) sequence of Maple statements, often called the body of the if statement.
The effect of an if statement is to divert the flow of control, under the right conditions, to the body of the statement. If the condition expression evaluates to true, the flow of control moves into the body of the if statement. Otherwise, if the condition expression evaluates to FAIL or false, Maple exits the if statement and the flow of control continues at the statement (if any) following the if statement.
if 2 < 3 then print( "HELLO" ) end if;
HELLO
if 2 > 3 then print( "GOODBYE" ) end if;
More generally, an if statement has the syntax
consequent
else
alternative
Here, consequent and alternative are statement sequences. If the condition expression evaluates to true, the consequent branch of the if statement is executed. Otherwise, the alternative branch is executed.
if 2 < 3 then print( "CONSEQUENT" ) else print( "ALTERNATIVE" ) end if;
CONSEQUENT
if 2 > 3 then print( "CONSEQUENT" ) else print( "ALTERNATIVE" ) end if;
ALTERNATIVE
The most general form of an if statement can have several conditions, corresponding consequents, and an optional alternative branch. This general form has the syntax:
if condition1 then
consequent1
elif condition2 then
consequent2
....
in which there can be any number of branches preceded by elif. The effect of this general form of the if statement is to divert the flow of control into the first branch whose conditional expression evaluates to true. This means that the order of the elif branches can affect the behavior of the if statement.
The branch introduced by else is optional. If it is present, and none of the earlier condition expressions evaluates to true, then control flows into the else branch. If it is not present, and none of the earlier condition expressions evaluates to true, then the flow of execution continues with the first statement following the entire if statement.
if 2 > 3 then print( "CONSEQUENT1" ) elif 3 > 4 then print( "CONSEQUENT2" ) elif 1 < 5 then print( "CONSEQUENT3" ) elif 2 < 5 then print( "CONSEQUENT4" ) else print( "ALTERNATIVE" ) end if;
CONSEQUENT3
if 2 > 3 then print( "CONSEQUENT1" ) elif 3 > 4 then print( "CONSEQUENT2" ) elif 1 > 5 then print( "CONSEQUENT3" ) elif 2 > 5 then print( "CONSEQUENT4" ) else print( "ALTERNATIVE" ) end if;
The else branch, if present, must appear last.
An if statement can appear at the top level, as in the examples shown above, but is most commonly used within a procedure or module definition.
A typical use of the if statement is to control the flow of execution inside a procedure, depending on information coming from the arguments passed to it.
p := proc( expr ) if type( expr, 'numeric' ) then sin( 2 * expr ) elif type( expr, { '`+`', '`*`' } ) then map( thisproc, _passed ) else 'procname'( _passed ) end if end proc:
p( 2 );
sin⁡4
p( x );
p⁡x
p( x + 1 );
p⁡x+sin⁡2
In this example, the procedure p uses the type command to examine its argument expr. If the argument is numeric, then it computes the value as sin( 2 * expr ). Otherwise, if the argument is either a sum or a product, the procedure maps itself over the operands of the expression. Otherwise, the procedure returns unevaluated.
Using if Statements in Expressions
In addition to being used as a stand-alone statement, an if statement can be used as an expression or within an expression.
The value of such an embedded if statement is the value of the last expression computed within the branch that was executed.
In the example below, an if statement is embedded within a call to the String function. The value will be one of "st", "nd", "rd", or "th" depending on the value of variable a:
a := 3;
a≔3
s := String(a, if a = 1 then "st" elif a = 2 then "nd" elif a = 3 then "rd" else "th" end if);
s≔3rd
The if Command
There is an older operator form of branching that can be used within an expression. In this form, if is always called with three arguments. The if operator has the following syntax:
`if`( condition, consequent, alternative )
The first argument condition is a Boolean-valued expression. The second argument consequent is an expression to evaluate if the first argument evaluates to the value true. The third argument is an expression to evaluate if the first argument evaluates to either false or FAIL.
`if`( 1 < 2, a, b );
3
`if`( 1 > 2, a, b );
b
Note that the name if must be enclosed in name (left) quotes in this form.
The if command evaluates only one of its second and third arguments, determined by the value of the first argument. The other argument is not evaluated.
a := 2/3:
sin( `if`( a > 0, Pi / 2, -Pi / 2 ) );
However, the if command is much more limited than the if statement. The consequent and alternative must be single expressions, and there is nothing corresponding to the elif parts of the statement form.
Loops
To cause a statement, or sequence of statements, to be run more than once, use a loop statement. Maple has a general and flexible loop statement.
The simplest loop has the form do end do. This loop does not perform any tasks.
A loop statement has one of the following general forms.
for var from start to finish by increment while condition do
end do
until condition
for var in container while condition do
The first line in each of these forms is called the loop header or, more formally, the loop control clause. The statseq part of the loop is a (possibly empty) sequence of statements, referred to as the body of the loop.
Each clause that occurs before the keyword do in the loop header is optional.
Since most of the examples below are infinite loops; you must interrupt the Maple computation to terminate the loop. For more information, see Interrupting a Maple Computation.
do end do;
by -14 do end do;
for i do end do;
from 42 do end do;
to 3 do end do;
while true do end do;
do until false;
If more than one of the optional clauses appears in the loop header, they may appear in any order, except that the for clause, if present, must appear first.
While Loops
One simple kind of terminating loop is the while loop.
while condition do
end do;
The loop header of a while loop involves only a single termination condition introduced by the keyword while. The loop repeats the statement sequence statseq as long as the Boolean-valued expression condition holds.
In this example, a loop counts the number of primes whose square is less than 1000.
count := 0: p := 2: while p^2 < 1000 do count := 1 + count; p := nextprime( p ) end do: count;
11
This example uses the nextprime command, which returns the least prime greater than its argument. The name count is given the initial value 0, and the name p, which is used to store the current prime, is initially set to 2. The loop condition is the expression p^2 < 1000, appearing after the keyword while and before the keyword do. This condition is evaluated at the beginning of each iteration of the loop. If the condition evaluates to true, the body of the loop is executed. If the condition evaluates to false or FAIL, the code continues to execute at the next statement following the loop statement.
If the condition expression evaluates to a value other than true, false or FAIL, an exception is raised.
while 3 do end do;
Error, invalid boolean expression: 3
while u < v do end do;
Error, cannot determine if this expression is true or false: u < v
For more information on Boolean expressions, see Boolean and Relational Expressions.
Until Loops
Another kind of terminating loop is the until loop.
do
until condition;
Like a while loop, an until loop has a single terminating condition, introduced by the keyword until. The until loop differs from the while loop in several respects:
The until clause appears in place of end do rather than in the loop header.
The condition is tested at the end of each iteration of the loop, instead of the beginning. As a consequence, the loop's statseq will always be executed at least once.
The loop repeats until the condition holds.
If the condition evaluates to FAIL, an exception is raised.
A benefit of checking the condition at the end of the loop is that the condition may depend on values only calculated for the first time within the loop.
In this example, an until loop is used to implement the functionality of nextprime, yielding the next prime number after a given number, even if the given number is already prime.
N := 23; do N := N + 1 until isprime(N): N;
N≔23
29
Had this been written as a while loop with condition not isprime(N), the result would have been 23, not 29.
Counted Loops
You can use a loop to repeatedly execute a sequence of statements a fixed number of times. These loops use the from and to clauses.
from 1 to 3 do print( "HELLO" ) end do;
or equivalently
to 3 do print( "HELLO" ) end do;
If the from clause is omitted, the default value of 1 is used.
Inductive Loops
The most common kind of loop is an inductive loop which is similar to a counted loop, but uses an induction variable whose value changes at each iteration of the loop. This is a particular kind of for loop with the general form
for var from start to finish by increment do
The default value for start is 1, for finish is infinity, and for increment is 1.
for i to 3 do print( i ) end do;
This loop performs the following tasks:
Maple assigns i the (default) value 1 since a starting value was not specified.
Because 1 is less than 3, Maple executes the statement in the body of the loop, in this case, printing the value of i.
Then i is incremented by 1 and tested again.
The loop executes until i>3. In this case, when the loop terminates, the final value of i is 4.
i;
In the next example, the increment is a negative number.
for i from 7 to 2 by -2 do print( i ) end do;
7
5
Note: Since loops are increasing by default (increment by 1), the statement for i from 7 to 2 do print (i) end do; does not do anything unless you specify the increment as a negative number. In this case, the loop increment is -2.
Loop control parameters (start, finish, and increment) do not need to be integers.
for i from 0.2 to 0.7 by 0.25 do print( i ) end do;
0.2
0.45
0.70
In addition to iterating over a numeric range, you can iterate over a range of characters. In this case, you must specify both the initial value start and the final value finish for the induction variable. Furthermore, the value of increment must be an integer.
for i from "a" to "g" by 2 do print( i ) end do;
c
e
g
Iterating over a Data Structure
An alternative form of the loop statement allows you to iterate over the operands of an expression (often, a data structure such as a set or list).
for var in expr do
The induction variable var takes on, successively, the operands of the expression expr. There are a few exceptions.
First, if expr is an expression sequence, it does not have operands as such, but the induction variable var iterates over the operands of the list [ expr ].
If expr is a table, the loop iterates over [entries]( expr ). (For more information on entries, see Extracting Data.) The order in which these entries are visited is not specified and may vary from one session to another.
Finally, if expr is an rtable, the loop iterates over the entries of expr, but the order of the iteration is not specified.
for i in [ 1, 2, 3 ] do print( i ) end do;
Note that there is a difference between the loop above and the seemingly equivalent loop
for i from 1 to 3 do print( i ) end do;
The difference is the value of the induction variable i at the end of the loop. To see this, evaluate the induction variable i immediately after running the loop to display its value.
for i in [ 1, 2, 3 ] do end do: i;
for i from 1 to 3 do end do: i;
It is also possible to specify a pair of variables for var, separated by a comma. In this case, during each iteration of the loop, the first variable takes as value the index of the operand in expr, and the second variable takes on the corresponding value as described previously.
M := LinearAlgebra:-RandomMatrix(3,4):
for ind, val in M do if val < 0 then M[ind] := -val end if end do;
M;
Using Loops in Expressions
In addition to being used as a stand-alone statement, a loop can also be used as an expression or within an expression by enclosing it in parentheses. In the case where such a loop is the only expression within a list, set, or function call, on the right hand side of an assignment, or the sole argument to a return statement, the parentheses may be omitted.
The value of such an embedded loop statement is a sequence of the last value computed during each iteration of the loop.
The example below generates a list of all primes below a specified upper bound. The assignment to i initializes it and also serves to include the number 2 in the result. The i in the body of the loop adds each new prime in turn to the result.
N := 30:
[(i := 2), (while (i := nextprime(i)) < N do i end do)];
2,3,5,7,11,13,17,19,23,29
Looping Commands
Maple provides commands to create some commonly used types of loops. These commands are generally meant to build expressions without creating many intermediate expressions.
The map Command
The map command applies a function to every element of an aggregate object. The simplest form of the map command is
map( f, x )
where f is a function and x is an expression. The map command replaces each operand elem of the expression x with f(elem).
For tables and Arrays (or other rtables), the function is applied to each entry.
map( f, [a,b,c] );
f⁡a,f⁡b,f⁡c
Given a list of integers, you can create a list of their absolute values and of their squares by using the map command.
L := [ -1, 2, -3, -4, 5 ];
L≔−1,2,−3,−4,5
q:=map(abs, L);
q≔1,2,3,4,5
map(x->x^2, L);
1,4,9,16,25
The general syntax of the map command is
map( f, x, y1, ..., yn )
where f is a function, x is any expression, and y1, ..., yn are expressions. The action of map is to replace each operand of x such that the ith operand of x is replaced by f(op(i,x), y1, ..., yn).
map( f, a+b+c, x, y );
f⁡a,x,y+f⁡b,x,y+f⁡c,x,y
map( (x,y) -> x^2+y, L, 1);
2,5,10,17,26
For more information and examples, see Basic Data Structures.
The select, remove, and selectremove Commands
The select, remove, and selectremove commands also operate on the operands of an expression. The select command returns the operands for which the specified Boolean-valued function returns true. The remove command returns the operands for which the specified Boolean-valued function returns false. The selectremove command returns two objects: the operands for which the specified Boolean-valued function returns true and the operands for which the specified Boolean-valued function returns false. The select, remove, and selectremove commands have the same syntax as the map command.
X := -3*y^4*z - w*y*z^2 + 2*x*y^2 + 2*y^3 + 3*w*z;
X≔−3⁢y4⁢z−w⁢y⁢z2+2⁢x⁢y2+2⁢y3+3⁢w⁢z
select(has, X, z);
−3⁢y4⁢z−w⁢y⁢z2+3⁢w⁢z
remove( x -> degree(x)>3, X );
2⁢x⁢y2+2⁢y3+3⁢w⁢z
For more information on these commands, see Other Data Structure Operations or refer to the select help page.
The zip Command
The zip command merges two lists or Arrays and then applies a binary function. The zip command has two forms
zip(f, u, v)
zip(f, u, v, d)
where f is a binary function, u and v are both lists or rtables, and d is any value. The zip command takes each pair of operands u[i], v[i], and creates a new list or vector from f(u[i], v[i]).
zip( (x,y) -> x || y, [a,b,c,d,e,f], [1,2,3,4,5,6] );
a1,b2,c3,d4,e5,f6
If the lists or vectors are not the same length, the length of the result depends on whether you provide the argument d.
If you do not specify d, the length of the result is the same as the length of the smaller list or vector.
zip( (x,y) -> x+y, [a,b,c,d,e,f], [1,2,3] );
a+1,b+2,c+3
If d is specified, the length of the result of the zip command is the same as the length of the longer list or vector. Maple replaces the missing value(s) with d.
zip( (x,y) -> x+y, [a,b,c,d,e,f], [1,2,3], xi );
a+1,b+2,c+3,d+ξ,e+ξ,f+ξ
Non-Local Flow Control
There are a couple of statements that are generally used in procedures to control how execution of the procedure ends: return and error. For more information on these statements, see Procedures.
The return Statement
The return statement causes an immediate return to the point where the current procedure was invoked.
In Command-line Maple, the return statement causes an error if it is run at the top level: Error, return out of context. In the Standard worksheet interface, return can be used at the top level in conjunction with DocumentTools:-RunWorksheet.
The error Statement and Exception Handling
The error statement raises an exception and interrupts the execution of the current statement. If the exception is not caught (see the following section), a message is printed indicating that an error occurred.
error string
error string, parameter1, parameter2, ...
In the first case, an error message is given as a string.
error "my error";
Error, my error
In the second case, string contains several placeholders of the form %n or %-n, where n is a positive integer, to include the provided parameters in the message.
The placeholder %n is replaced by the nth parameter given. The placeholder %-n is replaced by the ordinal form of the nth parameter, which should evaluate to an integer. The special placeholder %0 is replaced with the sequence of all parameters separated by commas and spaces.
x := a+b: n := 10;
n≔10
error "my error in %1 of the %-2 kind", x, n;
Error, my error in a+b of the 10th kind
Trapping Errors
The try statement is a mechanism for executing procedure statements in a controlled environment so that if an error occurs, it does not immediately terminate the procedure. The try statement has the following syntax
try tryStatSeq
catch catchStrings : catchStatSeq
finally finalStatSeq
end try
This statement can include several catch clauses. The finally clause is optional.
If procedure execution enters a try...catch block, the tryStatSeq is executed. If no exceptions occur during the execution of tryStatSeq, the finalStatSeq in the finally clause (if present) is executed. Execution then continues with the statement after end try.
If an exception occurs during the execution of tryStatSeq, execution of tryStatSeq terminates immediately. The exception object corresponding to the exception is compared against each catchString. Any number of catch clauses can be provided, and each can have any number of catchStrings separated by commas. Alternatively, a catch clause does not need to have a catch string. Any given catchString (or a catch clause without one) can appear only once in a try...end try construct.
If a matching catch clause is found, or the catch clause contains no catchStrings, the catchStatSeq of that catch clause is executed, and the exception is considered to have been caught. If no matching catch clause is found, the exception is considered not caught, and is re-raised outside of the try block.
When Maple searches for a matching catch clause, the following definition of "matching" is used.
Neither the exception object nor the catchStrings are evaluated (the exception object has already been evaluated by the error statement that produced it).
The catchStrings are considered to be prefixes of the exception object's msgString. If a catchString has n characters, only the first n characters of the msgString need to match the catchString. This permits the definition of classes of exceptions.
A catch clause without a catchString matches any exception.
The "result" of a try statement (the value that % returns if it is evaluated immediately after execution of the try statement) is the result of the last statement executed in the try statement.
A catchStatSeq can contain an error statement with no arguments, which also re-raises the exception. When an exception is re-raised, a new exception object is created that records the current procedure name, and the message and parameters from the original exception.
Normally, the finalStatSeq of the finally clause, if there is one, is always executed before control leaves the try statement. This is true in the case that an exception occurs, independent of whether it is caught or whether another exception occurs in the catch clause.
This is true even if a catchStatSeq re-raises the exception, raises a new one, or executes a return, break, or next statement.
Under certain abnormal circumstances, the finalStatSeq is not executed:
If an exception is caught in an interactive debugger session and you exit the debugger
If one of the following untrappable exceptions occurs, the exception is not caught, and finalStatSeq is not executed:
A computation timed out. This exception can only be caught by the timelimit command, which raises a "time expired" exception that can be caught. For more information on the timelimit command, refer to the timelimit help page.
A computation has been interrupted. In other words, you pressed Ctrl+C, Break, or equivalent.
Internal system error. This exception indicates a bug in Maple itself.
ASSERT or local variable type assertion failure. Assertion failures cannot be trapped because they indicate a coding error, not an algorithmic failure.
Stack overflow. If a stack overflow occurs, there is generally not enough stack space to perform tasks such as running cleanup code.
If an exception occurs during the execution of a catchStatSeq or the finalStatSeq, it is treated in the same way as if it occurred outside the try...end try statement.
Using try Statements in Expressions
A try statement can be used as an expression or within an expression.
The value of such an embedded try statement is the value of the last expression computed within the last branch that was executed:
If there was a non-empty finally clause, the result is that of the last expression computed in the finalStatSeq.
If no exception occurred, the result is that of the last expression computed in the tryCatchSeq.
If an exception did occur and was caught, the result is that of the last expression computed in the relevant catchStatSeq.
If there was an exception and it was not caught, the evaluation of the entire expression is aborted just as it would be if no exception handling statement were involved.
Example 1
A useful application of the try and error statements is to stop a large computation as quickly and cleanly as possible. For example, suppose that you are trying to compute an integral by using one of several methods, and in the middle of the first method, you determine that it will not succeed. You want to stop that method and try another one. The following code implements this example.
try result := MethodA(f,x) catch "FAIL": result := MethodB(f,x) end try:
MethodA can stop its computation at any time by executing the statement error "FAIL". The catch clause catches that exception, and proceeds to try MethodB. If any other error occurs during the execution of MethodA, or if an error occurs during the execution of MethodB, it is not caught.
Example 2
Another useful application of the try statement is to ensure that certain resources are released when you are done with them, regardless of whether anything went wrong while you were using them.
Use the following code to access the Maple I/O facilities to read the lines of a file and process them in some way.
f := fopen("myfile",READ,TEXT): try line := readline(f); while line < 0 do ProcessContentsOfLine(line); line := readline(f) end do finally fclose(f) end try:
In this example, if any exception occurs while reading or processing the lines of the file, it is not caught because there is no catch clause. However, fclose(f) is executed before execution leaves the try statement, regardless of whether there was an exception.
The next example uses both catch and finally clauses to write to a file instead of reading from one.
f := fopen("myfile",WRITE,TEXT): try for i to 100 do fprintf(f,"Result %d is %q\n",i,ComputeSomething(i)) end do catch: fprintf(f,"Something went wrong: %q\n",lastexception); error finally fclose(f) end try:
If any exception occurs, it is caught with the catch clause having no catchString, and the exception object is written into the file. The exception is re-raised by executing the error statement with no msgString. In all cases, the file is closed by executing fclose(f) in the finally clause.
5.7 The use Statement
The use statement specifies local bindings of names, module exports, and operator overriding. It has the following syntax:
use exprseq in
stateseq
end use
where stateseq is a sequence of statements and exprseq is a sequence of expressions.
The expressions can be any of the following.
equation of the form name = expression
module member selection m:-e, which is equivalent to the equation e = m:-e
module expression m, which is equivalent to the equations e = m:-e for all exports e of m.
For more information about modules and member selection, see Programming with Modules.
Running a use statement executes the body of the statement. Each occurrence of a name that appears on the left side of any of the binding equations is replaced by the right side of the corresponding equation.
For example,
use f = sin, g = cos in f( x )^2 + g( x )^2 end use;
sin⁡x2+cos⁡x2
The following example establishes local bindings for all of the exports of the StringTools package.
use StringTools in s := Random( 10, 'lower' ); Reverse( s ) end use;
s≔yhcmxxkyzm
mzykxxmchy
Among these are the names Random and Reverse. Without the use statement enclosing them, the two statements would have to be written using fully qualified names.
s := StringTools:-Random( 10, 'lower' );
s≔ifmmfydhnl
StringTools:-Reverse( s );
lnhdyfmmfi
You can employ the use statement to establish general name bindings.
use a = 2, b = 3, c = 4 in a + b + c end use;
9
(This is useful when the names bound are used many times within the body of the use statement.)
The use statement is unique in Maple. It is the only Maple statement that is resolved during the automatic simplification process rather than during the evaluation process. To see this, consider the following simple procedure.
p := proc( x, y ) use a = x + y, b = x * y in a / b end use end proc;
p≔procx,yx+y/y*xend proc
Note that there is no use statement in the procedure after it has been processed, and a and b in the body have been replaced by the values on the right-hand side of the binding equations. To see that this processing occurred during automatic simplification (of the procedure definition), enclose the procedure definition in unevaluation quotes.
p := 'proc( x, y ) use a = x + y, b = x * y in a / b end use end proc';
use statements can be nested.
use a = 2, b = 4 in use x = 3, y = 5 in a * x + b * y end use end use;
26
If a name is bound in use statements at two different levels of nesting, the innermost binding visible at the level of an expression is used.
use a = 2 in a^2; use a = 3 in a^2 end use end use;
In the following example, the inner binding of the value 3 to the name a takes precedence, so the value of the expression a + b (and therefore the entire statement) is the number 6. The inner binding of 3 to a has an effect only within the body of the inner use statement. Once the execution has exited the inner use statement, the binding of 2 to a is restored.
use a = 2, b = 3 in # here a is bound to 2 and b to 3 use a = 3 in # here, b is still bound to 3, but a is bound to 3 a + b end use; # binding of a to 2 is restored a + b end use;
6
The use statement also allows you to rebind Maple operators to override their default behavior. The following is an example in which addition and multiplication are replaced by nonstandard meanings.
use `+` = ((x,y) -> (x+y) mod 3), `*` = ((x,y) -> (x*y) mod 3) in 1 + 2 * 4 end use;
0
The following operators can have their default behavior overridden by a use statement.
@
@@
%
%%
%%%
.
+
*
-
/
mod
^
!
union
minus
intersect
subset
in
$
and
or
not
xor
implies
=
<>
<
<=
assuming
<|>
<,>
[]
{}
?()
?[]
~
Notes:
The following operators cannot be rebound: concatenation operator (||), member selection operator (:-), type operator (::), range (..), comma (,), functional operator (->), and assignment statement (:=). The relational operators > and >= can be rebound, but not independently of < and <=, respectively.
All of the element-wise operators are processed through the element-wise operator (~).
The operators - and / are treated as unary operators (that represent negation and inversion, respectively). Subtraction is represented internally in Maple by forming addition and negation: a - b = a + (-b). Division is formed in a similar way. Therefore, it is not necessary to override the binary infix operators - and /.
Note also that an expression such as a + b + c + d is treated as though it were parenthesized as ((a + b) + c) + d, so that each + operator is binary. For example,
use `+` = F in a + b + c + d; a + ( ( b + c ) + d ) end use;
F⁡F⁡F⁡a,b,c,d
F⁡a,F⁡F⁡b,c,d
5.8 Other Statements
The quit Statement
The Maple keywords quit, done, and stop perform the same task and, when entered in the command-line interface, cause the Maple process to terminate.
quit
done
stop
Note: The quit statement cannot be used in the Maple standard interface. In the standard interface, use File > Close Document to end your Maple session.
quit, stop, and done are available as command names if quoted using name quotes. These forms allow you to exit Maple while passing an integer in the range 0 .. 255 as an argument to be returned to the calling process as exit status.
The save Statement
You can save Maple expressions to a file by using the save statement. It has the general form
save name1, name2, ..., nameN, file
The names namei are names (that have assigned values) to be saved to the file file.
Normally, the file name file is a string.
For example, make the following three assignments and run the subsequent save statement.
a := proc( x ) sin( x / 2 ) end proc:
b := 42:
c := "some text":
save a, b, c, "myfile.txt";
The file myfile.txt is created in the current directory (assuming adequate file permissions) containing the following Maple assignment statements.
a := proc (x) sin(1/2\*x) end proc; b := 42; c := "some text";
The read Statement
The read statement takes the following form.
read filename
where filename is a string.
read "myfile.txt";
c ≔ some text
b ≔ 42
a ≔ procxsin⁡1/2*xend proc
The file named by filename must consist of valid Maple language statements. The statements in the file are executed as they are read, as though they were input into the Maple session in which the read statement was entered. Maple displays the results of executing each statement. However, the input statements are not echoed to the interface, by default. To change this, set the interface variable echo to a value of 2 or higher.
interface( 'echo' = 2 ):
5.9 Exercises
Find the product of the square root of all prime numbers less than 100.
Hint: The function isprime determines the primality of an integer.
Find the sum of all odd composite numbers less than 150.
Find the sum of the first 30 powers of 2.
Write a looping structure that finds the four substrings (of a string assigned to the name MyString) containing only lowercase letters, uppercase letters, decimal digits, and special characters.
Hint: You can use relational operators to compare characters.
Write a procedure, SPLIT, that, on input of a product f and a variable x, returns a list of two values. The first item in the list should be the product of the factors in f that are independent of x, and the second item should be the product of the factors that contain an x.
Hint: Use the has, select, remove, and selectremove commands.
Download Help Document