Expressions
Expressions
An expression is any construct that produces a value. Expressions include any combination of literal values, function or method calls, assignment expressions, object constructors, as well as arithmetical, relational and logical operations.
Arithmetic operators
Morpho provides the standard binary arithmetic operators
| Operator | Description |
|---|---|
+ |
Addition |
- |
Subtraction |
* |
Multiplication |
/ |
Division |
^ |
Exponentiation |
Hence, Morpho can be used, among other things, as an (over-engineered) pocket calculator like so:
print 2^8-1
Comparison operators
Comparisons between expressions can be achieved using relational operators,
| Operator | Description |
|---|---|
< |
Less than |
> |
Greater than |
== |
Equal to |
!= |
Not equal to |
<= |
Less than or equal to |
>= |
Greater than or equal to |
all of which return true or false. Not all expressions can be
compared; Complex numbers for example, can be tested for equality but
not compared so
print 1im < 2 // Invalid
throws a InvldOp error. Equality tests are more complicated than they
appear. Comparisons of objects are only equal if they refer exactly to
the same object, so
print [1,2,3] == [1,2,3]
prints false because two different Lists are created and compared,
even though their contents are identical. A few object types support
"deep" equality comparison, such as Strings and Tuples. Hence
print (1,2,3) == (1,2,3)
print "Hello" == "Hello"
both print true.
Logical operators
Finally, Morpho provides the logical operators
::: center :::
which implement the Boolean algebra. All of these operators consider the
two values false and nil to be false; any other value is
considered to be true. This is very different from C and some other
languages, where the integer value 0, and sometime even other values,
are also considered to be false. In Morpho, 0 (like
any other number) is considered to be true.
Like C, however, the logical operators do not always cause evaluate both operands to be evaluated. If the left operand of the AND operator is false, for example, the right hand operand is not evaluated because the expression is manifestly false. You can see this explicitly in the following example
fn f() {
print "f was evaluated!"
return true
}
print true && f() // f is evaluated
print false && f() // f is not evaluated
Conversely, if the left operand of the OR operator || is true, the
right hand operand isn't evaluated because it's clear the composite
expression must be true.
print true || f() // f is not evaluated
print false || f() // f is evaluated
Since the NOT operator
* has only one operand, it is always evaluated. \section{Assignment} The contents of variables can be changed using assignment expressions. The operator \lstinline=!
is used to indicate assignment: the operator on the left hand is called
the assignment target and is the variable or component to be modified;
the operand on the right hand side is the value to be assigned.
An assignment statement can be as simple as assigning a value
foo = 1
or could involve changing the contents of a collection using index notation
foo[0] = 1
A common use of assignment is to capture the return value of a function
foo = sin(Pi/4)
Morpho also provides a number of shorthand assignment operators that retrieve and modify the contents of an assignment target and then store the result back in the same target:
-
+=Increments the target by a given value, e.g.foo += 1 -
-=Decrements the target by a given value, e.g.foo -= 1 -
*=Multiplies the target by a given value, e.g.foo *= 2 -
/=Divides the target by a given value, e.g.foo /= 2
These shorthand operators are provided purely for the convenience of the programmer and each is entirely equivalent to a regular longhand assignment, e.g.
foo += 1
could equally be written as
foo = foo + 1
Because assignment operators in Morpho are expressions, they evaluate to a value which is always the value assigned. Hence
var a = 1
print a+=1
prints 2 which is the value of a+1
Other expressions
There are a few other types of expression and associated operators that are presented elsewhere in the book:
-
The Range constructors
..,...are discussed in Section [sec:Ranges]{reference-type="ref" reference="sec:Ranges"}. -
Function calls are introduced in Chapter Functions.
-
Method calls are denoted by a single dot
.and are explained in Section XXX.
Precedence
Compound expressions like 1 + 2 * 3 may appear ambiguous at first
sight because it is not obviously clear which of (1 + 2) * 3 = 9 or
1 + (2 * 3) = 7 is meant. Running this example
print 1 + 2 * 3
prints 7 rather than 9 because the multiplication operator * binds to
its operands with higher precedence than the addition operator +.
The order of precedence in Morpho is as follows
::: center
::: tabular
|c|c|l| & Operators &\
Highest & . & Method call\
& ^ & Power\
& -,
* & Unary minus, NOT\tabularnewline \hline & \lstinline*!,/ &
Multiplication and division\
& +,- & Addition and subtraction\
& .., ... & Range constructor\
& <, >, <=, >= & Comparison\
& ==, =* & Equality tests\tabularnewline \hline & \lstinline&&! &
AND\
& || & OR\
Lowest & =, +=, -=, *=, /= & Assignment\
:::
:::
The programmer is always free to use parentheses to control the order of evaluation, so
print (1 + 2) * 3
indeed prints 9. It is recommended to do so even if an expression is formally correct, but challenging for the reader to parse.