M has both unary and binary operators.
All unary operations have right to left precedence.
All M binary operations have strict left to right precedence. This includes all arithmetic, string, and logical operations. Hierarchies of operations require explicit establishment of precedence using parentheses (). Although this rule is counterintuitive, it is easy to remember and has no exceptions.
All arithmetic operators force M to evaluate the expressions to which they apply as numeric. The arithmetic operators are:
+ as a unary operator simply forces M to evaluate the expression following as numeric; as a binary operator it causes M to perform addition.
- as a unary operator causes M to negate the expression following; as a binary operator it causes M to perform subtraction.
* binary operator for multiplication.
** binary operator for exponentiation.
/ binary operator for fractional division.
\ binary operator for integer division.
# binary operator for modulo, that is, causes M to produce the remainder from integer division of the first argument by the second.
Remember that precedence is left to right for all arithmetic operators.
GTM>WRITE 1+1 2 GTM>WRITE 2-1 1 GTM>WRITE 2*2 4 GTM>WRITE 3**2 9 GTM>WRITE 4/2 2 GTM>WRITE 7 2 GTM>WRITE 7#3 1 GTM>
This simple example demonstrates how each arithmetic binary operation uses numeric literals.
GTM>WRITE +"12ABC" 12 GTM>WRITE --"-3-4" -3 GTM>
The first WRITE shows the unary plus sign (+) operation forcing the numeric evaluation of a string literal. The second WRITE demonstrates the unary minus sign (-). Note the second minus sign within the string literal does not cause subtraction, but rather, terminates the numeric evaluation with the result of negative three (-3). Each of the leading minus signs causes one negation and therefore, the result is negative three (-3).
M logical operators always produce a result that is TRUE (1) or FALSE (0). All logical operators force M to evaluate the expressions to which they apply as truth-valued. The logical operators are:
' unary NOT operator negates current truth-value; M accepts placement of the NOT operator next to a relational operator, for example, A'=B as meaning '(A=B).
&binary AND operator produces a true result only if both of the expressions are true.
! binary OR operator produces a true result if either of the expressions is true.
Remember that precedence is always left to right, and that logical operators have the same precedence as all other operators.
GTM>WRITE '0 1 GTM>WRITE '1 0 GTM>WRITE '5689 0 GTM>WRITE '-1 0 GTM>WRITE '"ABC" 1 GTM>
The above example demonstrates the unary NOT operation. Note that any non-zero numeric value is true and has a false negation.
GTM>WRITE 0&0 0 GTM>WRITE 1&0 0 GTM>WRITE 0&1 0 GTM>WRITE 1&1 1 GTM>WRITE 2&1 1 GTM>WRITE 0!0 0 GTM>WRITE 1!0 1 GTM>WRITE 0!1 1 GTM>WRITE 1!1 1 GTM>WRITE 2!1 1 GTM>
The above example demonstrates all cases covered by the binary logical operators.
All string operators force M to evaluate the expressions to which they apply as strings. The string operator is:
_binary operator causes M to concatenate the second expression with the first expresion
GTM>WRITE "B"_"A" BA GTM>WRITE "A"_1 A1 GTM>
The above example demonstrates M concatenation.
M relational operators always generate a result of TRUE (1) or FALSE (0). All numeric relational operators force M to evaluate the expressions to which they apply as numeric. The numeric relational operators are:
>binary arithmetic greater than
<binary arithmetic less than
The equal sign (=) does not force numeric evaluation, and should be viewed as a string operator. However, the equal sign between two numeric values tests for numeric equality.
Other numeric relations are formed using the logical NOT operator apostrophe (') as follows:
'> not greater than, that is, less than or equal to
'< not less than, that is, greater than or equal to
>= greater than or equal to, that is, not less than
<= less than or equal to, that is, not greater than
'= not equal, numeric or string operation
GTM>WRITE 1>2 0 GTM>WRITE 1<2 1 GTM>
The above example demonstrates the basic arithmetic relational operations.
GTM>WRITE 1'<2 0 GTM>WRITE 2'<1 1 GTM>
The above example demonstrates combinations of arithmetic, relational operators with the logical NOT operator.
M relational operators always generate a result of TRUE (1) or FALSE (0). All string relational operators force M to evaluate the expressions to which they apply as strings. The string relational operators are:
= binary operator causes M to produce a TRUE if the expressions are equal.
[ binary operator causes M to produce a TRUE if the first expression contains the ordered sequence of characters in the second expression.
] binary operator causes M to produce a TRUE if the first expression lexically follows the second expression in the character encoding sequence, which by default is ASCII.
]] binary operator causes M to produce a TRUE if the first expression lexically sorts after the second expression in the subscript collation sequence.
Note that all non-empty strings lexically follow the empty string, and every string contains the empty string.
Other string relations are formed using the logical NOT operator apostrophe (') as follows:
'[ does not contain.
'] does not follow, that is, lexically less than or equal to.
']] does not sort after, that is, lexically less than or equal to in the subscript collation sequence.
'= not equal, numeric or string operation.
GTM>WRITE "A"="B" 0 GTM>WRITE "C"="C" 1 GTM>WRITE "A"["B" 0 GTM>WRITE "ABC"["C" 1 GTM>WRITE "A"]"B" 0 GTM>WRITE "B"]"A" 1 GTM>WRITE "A"]]"B" 0 GTM>WRITE "B"]]"A" 1
These examples demonstrate the string relational operators using string literals.
GTM>WRITE 2]10 1 GTM>WRITE 2]]10 0 GTM>WRITE 0]"$" 1 GTM>WRITE 0]]"$" 0
These examples illustrate that when using the primary ASCII character set, the main difference in the "follows" (]) operator and the "sorts-after" (]]) operator is the way they treat numbers.
GTM>WRITE 1=1 1 GTM>WRITE 1=2 0 GTM>WRITE 1="1" 1 GTM>WRITE 1=01 1 GTM>WRITE 1="01" 0 GTM>WRITE 1=+"01" 1 GTM>
These examples illustrate the dual nature of the equal sign operator. If both expressions are string or numeric, the results are straight forward. However, when the expressions are mixed, the native string data type prevails.
GTM>WRITE "a"'="A" 1 GTM>WRITE "FRED"'["RED" 0 GTM>WRITE "ABC"']"" 0
These examples demonstrate combinations of the string relational operators with the NOT operator.
The pattern match operator (?) causes M to return a TRUE if the expression ahead of the operator matches the characteristics described by the pattern following the operator. The pattern is not an expression.
Patterns are made up of two elements:
A repetition count
A pattern code, a string literal or an alternation list
The element following the pattern match operator may consist of an indirection operator, followed by an element that evaluates to a legitimate pattern.
The repetition count consists of either a single integer literal or a period (.) delimiter with optional leading and trailing integer literals. A single integer literal specifies an exact repetition count. The period syntax specifies a range of repetitions where the leading number is a minimum and the trailing number is a maximum. When the repetition count is missing the leading number, M assumes there is no minimum, (i.e., a minimum of zero). When the repetition count is missing the trailing number, M does not place a maximum on the number of repetitions.
The pattern codes are:
A alphabetic characters upper or lower case
C control characters ASCII 0-31 and 127
E any character; used to pass all characters in portions of the string where the pattern is not restricted
L lower-case alphabetic characters, ASCII 97-122
N digits 0-9, ASCII 48-57
P punctuation, ASCII 32-47, 58-64, 91-96, 123-126
U upper-case alphabetic characters, ASCII 65-90
Pattern codes may be upper or lower case and may be replaced with a string literal. GT.M allows the M pattern match definition of patcodes A, C, N, U, L, and P to be extended or changed, (A can only be modified implicitly by modifying L or U) and new patcodes added. For detailed information on enabling this functionality, see Chapter 12: “Internationalization”.
The GT.M compiler accepts pattern codes other than those explicitly defined above. If, at run-time, the pattern codes come into use and no pattern definitions are available, GT.M issues a run-time error (PATNOTFOUND). GT.M does not currently implement a mechanism for Y and Z patterns and continues to treat those as compile-time syntax errors.
GTM>WRITE "ABC"?3U 1 GTM>WRITE "123-45-6789"?3N1"-"2N1"-"4N 1
The first WRITE has a simple one-element pattern while the second has multiple elements including both codes and string literals. All the repetition counts are fixed.
I x?.E1C.E W !,"Must not contain a control character" Q
This example uses a pattern match to test for control characters.
I acn?1U.20A1","1U.10A D .S acn=$G((^ACX($P(acn,","),$P(acn,",",2)))
This example uses a pattern match with implicit minimums to determine that an "account number" is actually a name, and to trigger a look-up of the corresponding account number in the ^ACX cross index.
The pattern match operator accepts the alteration syntax. Alteration consists of a repeat count followed by a comma-delimited list of patatoms enclosed in parentheses "()". The semantic is that the pattern matches if any of the listed patterns matches the operand string. For example, ?1(2N1"-"7N,3N1"-"2N1"-"4N).1U might be a way to match either a social security number or a taxpayer ID. Since alternation is defined as one of the ways of constructing a patatom, alternation can nest (be used recursively).
Complex pattern matches may not be efficient to evaluate, so every effort should be made to simplify any commonly used pattern and to determine if more efficient alternative logic would be more appropriate.