Operators and Expressions
ObjectScript supports many different operators, which perform various actions, including mathematical actions, logical comparisons, and so on. Operators act on expressions, which are variables or other entities that ultimately evaluated to a value. This topic describes expressions and the operators.
Introduction to Operators and Expressions
Operators are symbolic characters that specify the action to be performed on their associated operands. Each operand consists of one or more expressions or expression atoms. When used together, an operator and its associated operands have the following form:
[operand] operator operand
Some operators take only one operand and are known as unary operators; others take two operands and are known as binary operators.
An operator and any of its operands taken together constitute an expression.
Assignment
Within ObjectScript the SET command is used along with the assignment operator ( = ) to assign a value to a variable. The righthand side of an assignment command is an expression:
SET value = 0
SET value = a + b
Within ObjectScript it is also possible to use certain functions on the lefthand side of an assignment command:
SET pies = "apple,banana,cherry"
WRITE "Before: ",pies,!
// set the 3rd commadelimited piece of pies to coconut
SET $Piece(pies,",",3) = "coconut"
WRITE "After: ",pies
Operator Precedence
Operator precedence in ObjectScript is strictly lefttoright; within an expression operations are performed in the order in which they appear. This is different from other languages in which certain operators have higher precedence than others. You can use explicit parentheses within an expression to force certain operations to be carried ahead of others.
WRITE "1 + 2 * 3 = ", 1 + 2 * 3,! // returns 9
WRITE "2 * 3 + 1 = ", 2 * 3 + 1,! // returns 7
WRITE "1 + (2 * 3) = ", 1 + (2 * 3),! // returns 7
WRITE "2 * (3 + 1) = ", 2 * (3 + 1),! // returns 8
Note that in InterSystems SQL operator precedence is configurable, and may (or may not) match the operator precedence in ObjectScript.
Unary Negative Operators
ObjectScript gives the unary negative operator precedence over the binary arithmetic operators. ObjectScript first scans a numeric expression and performs any unary negative operations. Then, ObjectScript evaluates the expression and produces a result.
WRITE 123  3,! // returns 126
WRITE 123 + 3,! // returns 126
WRITE (123  3),! // returns 120
Parentheses and Precedence
You can change the order of evaluation by nesting expressions within each other with matching parentheses. The parentheses group the enclosed expressions (both arithmetic and relational) and control the order in which ObjectScript performs operations on the expressions. Consider the following expression:
SET TorF = ((4 + 7) > (6 + 6)) // False (0)
WRITE TorF
Here, because of the parentheses, four and seven are added, as are six and six; this results in the logical expression 11 > 12, which is false. Compare this to:
SET Value = (4 + 7 > 6 + 6) // 7
WRITE Value
In this case, precedence proceeds from left to right, so four and seven are added. Their sum, eleven, is compared to six; since eleven is greater than six, the result of this logical operation is one (TRUE). One is then added to six, and the result is seven.
Note that the precedence even determines the result type, since the first expression’s final operation results in a boolean and the second expression’s final operation results in a numeric.
The following example shows multiple levels of nesting:
WRITE 1+2*34*5,! // returns 25
WRITE 1+(2*3)4*5,! // returns 15
WRITE 1+(2*(34))*5,! // returns 5
WRITE 1+(((2*3)4)*5),! // returns 11
Precedence from the innermost nested expression and proceeds out level by level, evaluating left to right at each level.
For all but the simplest ObjectScript expressions, it is good practice to fully parenthesize expressions. This is to eliminate any ambiguity about the order of evaluation and to also eliminate any future questions about the original intention of the code.
For example, because the && operator, like all operators, is subject to lefttoright precedence, the final statement in the following code fragment evaluates to 0:
SET x = 3
SET y = 2
IF x && y = 2 {
WRITE "True",! }
ELSE {
WRITE "False",! }
This is because the evaluation occurs as follows:

The first action is to check if x is defined and has a nonzero value. Since x equals 3, evaluation continues.

Next, there is a check if y is defined and has a nonzero value. Since y equals 2, evaluation continues.

Next, the value of 3 && 2 is evaluated. Since neither 3 nor 2 equal 0, this expression is true and evaluates to 1.

The next action is to compare the returned value to 2. Since 1 does not equal 2, this evaluation returns 0.
For those accustomed to many programming languages, this is an unexpected result. If the intent is to return True if x is defined with a nonzero value and if y equals 2, then parentheses are required:
SET x = 3
SET y = 2
IF x && (y = 2) {
WRITE "True",! }
ELSE {
WRITE "False",! }
Functions and Precedence
Some types of expressions, such as functions, can have side effects. Suppose you have the following logical expression:
IF var1 = ($$ONE + (var2 * 5)) {
DO ^Test
}
ObjectScript first evaluates var1, then the function $$ONE, then var2. It then multiplies var2 by 5. Finally, ObjectScript tests to see if the result of the addition is equal to the value in var1. If it is, it executes the DO command to call the Test routine.
As another example, consider the following logical expression:
SET var8=25,var7=23
IF var8 = 25 * (var7 < 24) {
WRITE !,"True" }
ELSE {
WRITE !,"False" }
ObjectScript evaluates expressions strictly lefttoright. The programmer must use parentheses to establish any precedence. In this case, ObjectScript first evaluates var8=25, resulting in 1. It then multiplies this 1 by the results of the expression in parentheses. Because var7 is less than 24, the expression in parentheses evaluates to 1. Therefore, ObjectScript multiplies 1 * 1, resulting in 1 (true).
StringtoNumber Conversion
A string can be numeric, partially numeric, or nonnumeric.

A numeric string consists entirely of numeric characters. For example, "123", "+123", ".123", "++0007", "0".

A partially numeric string is a string that begins with numeric symbols, followed by nonnumeric characters. For example, "3 blind mice", "12 degrees".

A nonnumeric string begins with a nonnumeric character. For example, " 123", "the 3 blind mice", "three blind mice".
Numeric Strings
When a numeric string or partially numeric string is used in an arithmetic expression, it is interpreted as a number. This numeric value is obtained by scanning the string from left to right to find the longest sequence of leading characters that can be interpreted as a numeric literal. The following characters are permitted:

The digits 0 through 9.

The PlusSign and MinusSign property values. By default these are the + and  characters, but are localedependent. Use the %SYS.NLS.Format.GetFormatItem()Opens in a new tab method to return the current settings.

The DecimalSeparator property value. By default this is the . character, but is localedependent. Use the %SYS.NLS.Format.GetFormatItem()Opens in a new tab method to return the current setting.

The letters e, and E may be included as part of a numeric string when in a sequence representing scientific notation, such as 4E3.
Note that the NumericGroupSeparator property value (the , character, by default) is not considered a numeric character. Therefore, the string "123,456" is a partially numeric string that resolves to the number "123".
Numeric strings and partial numeric strings are converted to canonical form prior to arithmetic operations (such as addition and subtraction) and greater than/less than comparison operations (<, >, <=, >=). Numeric strings are not converted to canonical form prior to equality comparisons (=, '=), because these operators are also used for string comparisons.
The following example shows arithmetic comparisons of numeric strings:
WRITE "3" + 4,! // returns 7
WRITE "003.0" + 4,! // returns 7
WRITE "++3" + 4,! // returns 7
WRITE "3 blind mice" + 4,! // returns 7
The following example shows less than (<) comparisons of numeric strings:
WRITE "3" < 4,! // returns 1
WRITE "003.0" < 4,! // returns 1
WRITE "++3" < 4,! // returns 1
WRITE "3 blind mice" < 4,! // returns 1
The following example shows <= comparisons of numeric strings:
WRITE "4" <= 4,! // returns 1
WRITE "004.0" <= 4,! // returns 1
WRITE "++4" <= 4,! // returns 1
WRITE "4 horsemen" <= 4,! // returns 1
The following example shows equality comparisons of numeric strings. Noncanonical numeric strings are compared as character strings, not as numbers. Note that –0 is a noncanonical numeric string, and is therefore compared as a string, not a number:
WRITE "4" = 4.00,! // returns 1
WRITE "004.0" = 4,! // returns 0
WRITE "++4" = 4,! // returns 0
WRITE "4 horsemen" = 4,! // returns 0
WRITE "4" = 4,! // returns 1
WRITE "0" = 0,! // returns 1
WRITE "0" = 0,! // returns 0
WRITE "0" = 0,! // returns 0
NonNumeric Strings
If the leading characters of the string are not numeric characters, the string’s numeric value is 0 for all arithmetic operations. For <, >, '>, <=, '<, and >= comparisons a nonnumeric string is also treated as the number 0. Because the equal sign is used for both the numeric equality operator and the string comparison operator, string comparison takes precedence for = and '= operations. You can prepend the PlusSign property value (+ by default) to force numeric evaluation of a string; for example, "+123". This results in the following logical values, when x and y are different nonnumeric strings (for example x=”Fred”, y=”Wilma”).
x, y  x, x  +x, y  +x, +y  +x, +x 

x=y is FALSE  x=x is TRUE  +x=y is FALSE  +x=+y is TRUE  +x=+x is TRUE 
x'=y is TRUE  x'=x is FALSE  +x'=y is TRUE  +x'=+y is FALSE  +x'=+x is FALSE 
x<y is FALSE  x<x is FALSE  +x<y is FALSE  +x<+y is FALSE  +x<+x is FALSE 
x<=y is TRUE  x<=x is TRUE  +x<=y is TRUE  +x<=+y is TRUE  +x<=+x is TRUE 
Expressions
An ObjectScript expression is one or more tokens that can be evaluated to yield a value. The simplest expression is simply a literal or variable:
SET expr = 22
SET expr = "hello"
SET expr = x
You can create more complex expressions using arrays, operators, or one of the many ObjectScript functions:
SET expr = +x
SET expr = x + 22
SET expr = array(1)
SET expr = ^data("x",1)
SET expr = $Length(x)
An expression may consist of, or include, an object property, instance method call, or class method call:
SET expr = person.Name
SET expr = obj.Add(1,2)
SET expr = ##class(MyApp.MyClass).Method()
You can directly invoke an ObjectScript routine call within an expression by placing $$ in front of the routine call:
SET expr = $$MyFunc^MyRoutine(1)
Expressions can be classified according to what kind of value they return:

An arithmetic expression contains arithmetic operators, gives a numeric interpretation to the operands, and produces a numeric result:
SET expr = 1 + 2 SET expr = +x SET expr = a + b
Note that a string used within an arithmetic expression is evaluated as a numeric value (or 0 if it is not a valid numeric value). Also note that using the unary addition operator (+) will implicitly convert a string value to a numeric value.

A string expression contains string operators, gives a string interpretation to the operands, and produces a string result.
SET expr = "hello" SET expr = "hello" _ x

A logical expression contains relational and logical operators, gives a logical interpretation to the operands, and produces a boolean result: TRUE (1) or FALSE (0):
SET expr = 1 && 0 SET expr = a && b SET expr = a > b

An object expression produces an object reference as a result:
SET expr = object SET expr = employee.Company SET expr = ##class(Person).%New()
Logical Expressions
Logical expressions use logical operators, numeric relational operators, and string relational operators. They evaluate expressions and result in a Boolean value: 1 (TRUE) or 0 (FALSE). Logical expressions are most commonly used with:
In a Boolean test, any expression that evaluates to a nonzero numeric value returns a Boolean 1 (TRUE) value. Any expression that evaluates to a zero numeric value returns a Boolean 0 (FALSE) value. InterSystems IRIS® data platform evaluates a nonnumeric string as having a zero numeric value. For further details, refer to StringtoNumber Conversion.
You can combine multiple Boolean logical expressions by using logical operators. Like all InterSystems IRIS expressions, they are evaluated in strict lefttoright order. There are two types of logical operators: regular logical operators (& and !) and shortcircuit logical operators (&& and ).
When regular logical operators are used to combine logical expressions, InterSystems IRIS evaluates all of the specified expressions, even when the Boolean result is known before all of the expressions have been evaluated. This assures that all expressions are valid.
When shortcircuit logical operators are used to combine logical expressions, InterSystems IRIS evaluates only as many expressions as are needed to determine the Boolean result. For example, if there are multiple AND tests, the first expression that returns 0 determines the overall Boolean result. Any logical expressions to the right of this expression are not evaluated. This allows you to avoid unnecessary timeconsuming expression evaluations.
Some commands allow you to specify a commaseparated list as an argument value. In this case, InterSystems IRIS handles each listed argument like an independent command statement. Therefore, IF x=7,y=4,z=2 is parsed as IF x=7 THEN IF y=4 THEN IF z=2, which is functionally identical to the shortcircuit logical operators statement IF (x=7)&&(y=4)&&(z=2).
In the following example, the IF test uses a regular logical operator (&). Therefore, all functions are executed even though the first function returns 0 (FALSE) which automatically makes the result of the entire expression FALSE:
LogExp
IF $$One() & $$Two() {
WRITE !,"Expression is TRUE." }
ELSE {
WRITE !,"Expression is FALSE." }
One()
WRITE !,"one"
QUIT 0
Two()
WRITE !,"two"
QUIT 1
In the following example, the IF test uses a shortcircuit logical operator (&&). Therefore, the first function is executed and returns 0 (FALSE) which automatically makes the result of the entire expression FALSE. The second function is not executed:
LogExp
IF $$One() && $$Two() {
WRITE !,"Expression is TRUE." }
ELSE {
WRITE !,"Expression is FALSE." }
One()
WRITE !,"one"
QUIT 0
Two()
WRITE !,"two"
QUIT 1
In the following example, the IF test specifies commaseparated arguments. The comma is not a logical operator, but has the same effect as specifying the shortcircuit && logical operator. The first function is executed and returns 0 (FALSE) which automatically makes the result of the entire expression FALSE. The second function is not executed:
LogExp
IF $$One(),$$Two() {
WRITE !,"Expression is TRUE." }
ELSE {
WRITE !,"Expression is FALSE." }
One()
WRITE !,"one"
QUIT 0
Two()
WRITE !,"two"
QUIT 1
Arithmetic Operators
The arithmetic operators interpret their operands as numeric values and produce numeric results. When operating on a string, an arithmetic operators treats the string as its numeric value, according to the rules described in StringtoNumber Conversion. ObjectScript provides the following arithmetic operators:
The unary positive operator (+) gives its single operand a numeric interpretation. It does this by sequentially parsing the characters of the string as a number, until it encounters a character that cannot be interpreted as a number. It then returns whatever leading portion of the string was a wellformed numeric (or it returns 0 if no such interpretation was possible). For example:
WRITE + "32 dollars and 64 cents" // 32
For details, see the Unary Positive (+) reference page.
The unary negative operator () reverses the sign of a numerically interpreted operand. For example:
SET x = 60
WRITE " x: ", x,! // 60
WRITE "x: ",x,! // 60
ObjectScript gives the unary negative operator precedence over the binary (twooperand) arithmetic operators.
For details, see the Unary Negative () reference page.
To return the absolute value of a numeric expression, use the $ZABS function.
The addition operator adds two numeric values. For example:
WRITE 2936.22 + 301.45 // 3237.67
For details, see the Addition (+) reference page.
The subtraction operator subtracts one numeric value from another. For example:
WRITE 2936.22  301.45 // 2634.77
For details, see the Subtraction () reference page.
The multiplication operator multiplies two numeric values. For example:
WRITE 9 * 5.5 // 49.5
For details, see the Multiplication (*) reference page.
The division operator divides one numeric value with another. For example:
WRITE 9 / 5.5 // 1.636363636363636364
For details, see the Division ( / ) reference page.
The integer operator divides one numeric value with another and discards any fractional value. For example:
WRITE "355 \ 113 = ", 355 \ 113 // 3
For details, see the Integer Division ( \ ) reference page.
When the two operands are positive, then the modulo operation is the remainder of the left operand integer divided by the right operand. For example:
WRITE "37 # 10 = ",37 # 10,! // 7
WRITE "12.5 # 3.2 = ",12.5 # 3.2,! // 2.9
For details, see the Modulo (#) reference page.
The exponentiation operator raises one numeric value to the power of the other numeric value. For example:
WRITE "9 ** 2 = ",9 ** 2,! // 81
For details, see the Exponentiation (**) reference page. Exponentiation can also be performed using the $ZPOWER function.
InterSystems IRIS supports two representations of numbers: ObjectScript decimal floatingpoint (referred to as decimal format) and IEEE doubleprecision binary floatingpoint (referred to as $DOUBLE, generally used for special purposes). ObjectScript automatically converts a decimal value to the corresponding $DOUBLE value in the following situations:

If an arithmetic operation involves a $DOUBLE value, ObjectScript converts all numbers in the operation to $DOUBLE.

If an operation results in a number that is too large to be represented in decimal format, ObjectScript automatically converts this number to $DOUBLE, rather than issuing a <MAXNUMBER> error.
For details on these formats, see Numeric Computing in InterSystems Applications.
Numeric Relational Operators
Numeric relational operators use the numeric values of the operands to produce a Boolean result. When operating on strings, a numeric relational operator treats each of the strings as its numeric value, according to the rules described in StringtoNumber Conversion.
Numeric relational operators should not be used to compare nonnumeric strings.
ObjectScript provides the following numeric relational operators:
The less than operator tests whether the left operand is less than the right operand. For example:
WRITE 9 < 6 // 0
For details, see the Less Than (<) reference page.
The greater than operator tests whether the left operand is greater than the right operand. For example:
WRITE 15 > 15 // 0
For details, see the Greater Than (<) reference page.
The less than or equal to operator tests whether the left operand is less or equal to than the right operand. For example:
WRITE 9 <= 6 // 0
See the Less Than or Equal To (<= or '>) reference page.
The greater than or equal to operator tests whether the left operand is greater than or equal to the right operand. For example:
WRITE 15 >= 15 // 1
See the Greater Than or Equal To (<= or '>) reference page.
InterSystems IRIS supports two representations of numbers: ObjectScript decimal floatingpoint (referred to as decimal format) and IEEE doubleprecision binary floatingpoint (referred to as $DOUBLE format, generally used for special purposes).
Lessthan/greaterthan comparisons between these formats are performed exactly, without rounding. However, equality comparisons between decimal and $DOUBLE numbers often yield unexpected results, and should be avoided. For further details, see Numeric Computing in InterSystems Applications.
Logical Comparison Operators
The logical comparison operators compare the values of their operands and return a boolean value: TRUE (1) or FALSE (0).
Precedence and Logical Operators
Because ObjectScript performs a strict lefttoright evaluation of operators, logical comparisons involving other operators must use parentheses to group operations to achieve the desired precedence. For example, you would expect the logical Or (!) test in the following program to return TRUE (1):
SET x=1,y=0
IF x=1 ! y=0 {WRITE "TRUE"}
ELSE {WRITE "FALSE" }
// Returns 0 (FALSE), due to evaluation order
However, to properly perform this logical comparison, you must use parentheses to nest the other operations. The following example gives the expected results:
SET x=1,y=0
IF (x=1) ! (y=0) {WRITE "TRUE"}
ELSE {WRITE "FALSE" }
// Returns 1 (TRUE)
Logical Operators
ObjectScript provides the following logical operators:
Not inverts the truth value of the boolean operand. If the operand is TRUE (1), Not gives it a value of FALSE (0). If the operand is FALSE (0), Not gives it a value of TRUE (1).
For example, the following statements produce a result of FALSE (0):
SET x=0
WRITE x
See the Not (') reference page.
And tests whether both its operands have a truth value of TRUE (1). If both operands are TRUE (that is, have nonzero values when evaluated numerically), ObjectScript produces a value of TRUE (1). Otherwise, ObjectScript produces a value of FALSE (0).
There are two forms to And:

The & operator evaluates both operands and returns a value of FALSE (0) if either operand evaluates to a value of zero. Otherwise it returns a value of TRUE (1).

The && operator evaluates the left operand and returns a value of FALSE (0) if it evaluates to a value of zero. Only if the left operand is nonzero does the && operator then evaluate the right operand. It returns a value of FALSE (0) if the right operand evaluates to a value of zero. Otherwise it returns a value of TRUE (1).
The following examples evaluate two nonzerovalued operands as TRUE and produces a value of TRUE (1).
SET A=4,B=1
WRITE A&B // TRUE (1)
See the And (& or &&) reference page. Also see the Not And (NAND) ('&) reference page.
Or produces a result of TRUE (1) if either operand has a value of TRUE or if both operands have a value of TRUE (1). Or produces a result of FALSE (0) only if both operands are FALSE (0).
There are two forms to Or:

The ! operator evaluates both operands and returns a value of FALSE (0) if both operand evaluates to a value of zero. Otherwise it returns a value of TRUE (1).

The  operator evaluates the left operand. If the left operand evaluates to a nonzero value, the  operator returns a value of TRUE (1) without evaluating the right operand. Only if the left operand evaluates to zero does the  operator then evaluate the right operand. It returns a value of FALSE (0) if the right operand also evaluates to a value of zero. Otherwise it returns a value of TRUE (1).
The following examples evaluate two TRUE (nonzero) operands, apply the Or to them, and produces a TRUE result:
SET A=5,B=7
WRITE "A!B = ",A!B,!
SET A=5,B=7
WRITE "AB = ",AB,!
See the Or (! or ) reference page. Also see the Not Or (NOR) ('!) reference page.
String Concatenate Operator (_)
The string Concatenate operator (_) interprets its two operands as strings and returns a string value that appends the second string to the first string.
The following example writes the string Highchair to the current device.
WRITE "High"_"chair"
For details, see the String Concatenate (_) reference page.
String Relational Operators
String relational operators use the string interpretation of the operands to produce a Boolean result. You can precede any of the string relational operators with the NOT logical operator (') to obtain the negation of the logical result. ObjectScript provides the following string relational operators:
The Equals operator tests two operands for string equality. When you apply Equals to two strings, ObjectScript returns a result of TRUE (1) if the two operands are identical strings with identical character sequences and no intervening characters, including spaces; otherwise it returns a result of FALSE (0). For example:
WRITE "SEVEN"="SEVEN" // 1
WRITE "SEVEN"="seven" // 0
WRITE "SEVEN"=" SEVEN " // 0
For details, see the Equals (=) reference page. Also see the Not Equals ('=) reference page.
Contains tests whether the sequence of characters in the right operand is a substring of the left operand. If the left operand contains the character string represented by the right operand, the result is TRUE (1). If the left operand does not contain the character string represented by the right operand, the result is FALSE (0). If the right operand is the null string, the result is always TRUE.
For example:
SET L="Steam Locomotive"
SET S="Steam"
WRITE L[S /// 1
For details, see the Contains ([) reference page. Also see the Does Not Contain ('[) reference page.
Follows tests whether the characters in the left operand come after the characters in the right operand in ASCII collating sequence. Follows tests both strings starting with the left most character in each.
For example:
WRITE "LAMPOON"]"LAMP" // 1
For details, see the Follows (]) reference page. Also see the Not Follows (']) reference page.
Sorts After tests whether the left operand sorts after the right operand in numeric subscript collation sequence. In numeric collation sequence, the null string collates first, followed by canonical numbers in numeric order with negative numbers first, zero next, and positive numbers, followed lastly by nonnumeric values.
For example:
WRITE 122]]2 // 1
For details, see the Sorts After (]]) reference page. Also see the Not Sorts After (']]) reference page.
Pattern Match Operator (?)
The ObjectScript pattern match operator tests whether the characters in its left operand are correctly specified by the pattern in its right operand.
For example, the following tests if the string ssn contains a valid U.S. Social Security Number (3 digits, a hyphen, 2 digits, a hyphen, and 4 digits):
SET ssn="123456789"
SET match = ssn ? 3N1""2N1""4N
WRITE match
For pattern syntax and other details, see the Pattern Match (?) reference page.
ObjectScript also supports regular expressions, a pattern match syntax supported (with variants) by many software vendors. Regular expressions can be used with the $LOCATE and $MATCH functions, and with methods of the %Regex.MatcherOpens in a new tab class. For details, see the Regular Expressions reference page.
These pattern match systems are wholly separate and use different syntaxes with different patterns and flags.
Indirection Operator (@)
Indirection is a technique that provides dynamic runtime substitution of part or all of a command line, a command, or a command argument by the contents of a data field.
Indirection is specified by the indirection operator (@) and, except for subscript indirection, takes the form:
@variable
where variable identifies the variable from which the substitution value is to be taken. All variables referenced in the substitution value are public variables, even when used in a procedure. The variable can be an array node.
The following routine illustrates that indirection looks at the entire variable value to its right.
IndirectionExample
SET x = "ProcA"
SET x(3) = "ProcB"
; The next line will do ProcB, NOT ProcA(3)
DO @x(3)
QUIT
ProcA(var)
WRITE !,"At ProcA"
QUIT
ProcB(var)
WRITE !,"At ProcB"
QUIT
For details, see the Indirection (@) reference page.
Although indirection can promote more economical and more generalized coding than would be otherwise available, it is never essential. You can always duplicate the effect of indirection by other means, such as by using the XECUTE command.