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