Skip to main content

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 right-hand 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 left-hand side of an assignment command:

 SET pies = "apple,banana,cherry"
 WRITE "Before: ",pies,!

 // set the 3rd comma-delimited piece of pies to coconut
 SET $Piece(pies,",",3) = "coconut"
 WRITE "After: ",pies

Operator Precedence

Operator precedence in ObjectScript is strictly left-to-right; 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. For example:

USER>WRITE "1 + 2 * 3 = ", 1 + 2 * 3
1 + 2 * 3 = 9
USER>WRITE 1 + 2 * 3
9
USER>WRITE 2 * 3 + 1
7
USER>WRITE 1 + (2 * 3)
7
USER>WRITE 2 * (3 + 1)
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. For example:

USER>WRITE -123 - 3
-126
USER>WRITE -123 + - 3
-126
USER>WRITE -(123 - 3)
-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 of operations. For example:

USER>SET TorF = ((4 + 7) > (6 + 6))
 
USER>WRITE TorF
0

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:

USER>SET Value = (4 + 7 > 6 + 6)
 
USER>WRITE Value
7

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:

USER>WRITE 1+2*3-4*5
25
USER>WRITE 1+(2*3)-4*5
15
USER>WRITE 1+(2*(3-4))*5
-5
USER>WRITE 1+(((2*3)-4)*5)
11

Precedence from the innermost nested expression and proceeds out level by level, evaluating left to right at each level.

Tip:

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 left-to-right precedence, the final statement in the following code fragment evaluates to 0:

USER>SET x = 3
 
USER>SET y = 2
 
USER>WRITE x && y = 2
0

This is because, within the last step, the evaluation occurs as follows:

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

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

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

  4. 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 non-zero value and if y equals 2, then parentheses are required:

USER>SET x = 3
 
USER>SET y = 2
 
USER>WRITE x && (y = 2)
1

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 example:

USER>SET var8=25,var7=23
 
USER>WRITE var8 = 25 * (var7 < 24)
1

ObjectScript evaluates expressions strictly left-to-right. The programmer must use parentheses to establish any precedence. In this case, ObjectScript first evaluates the logical expression var8 = 25, resulting in 1. It then multiplies this result with the results of (var7 < 24). The expression (var7 < 24) evaluates to 1. Therefore, ObjectScript multiplies 1 by 1, resulting in 1.

String-to-Number Conversion

A string can be numeric, partially numeric, or non-numeric.

  • 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 non-numeric characters. For example, "3 blind mice", "-12 degrees".

  • A non-numeric string begins with a non-numeric 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:

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:

USER>WRITE "3" + 4
7
USER>WRITE "003.0" + 4
7
USER>WRITE "++--3" + 4
7
USER>WRITE "3 blind mice" + 4
7

The following example shows less than (<) comparisons of numeric strings:

USER>WRITE "3" < 4
1
USER>WRITE "003.0" < 4
1
USER>WRITE "++--3" < 4
1
USER>WRITE "3 blind mice" < 4
1

The following example shows <= comparisons of numeric strings:

USER>WRITE "4" <= 4
1
USER>WRITE "004.0" <= 4
1
USER>WRITE "++--4" <= 4
1
USER>WRITE "4 horsemen" <= 4
1

The following example shows equality comparisons of numeric strings. Non-canonical numeric strings are compared as character strings, not as numbers. Note that –0 is a non-canonical numeric string, and is therefore compared as a string, not a number:

USER>WRITE "4" = 4.00
1
USER>WRITE "004.0" = 4
0
USER>WRITE "++--4" = 4
0
USER>WRITE "4 horsemen" = 4
0
USER>WRITE "-4" = -4
1
USER>WRITE "0" = 0
1
USER>WRITE "-0" = 0
0
USER>WRITE "-0" = -0
0

Non-Numeric 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 non-numeric 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 non-numeric 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, interprets the operands logically, 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 (an OREF):

     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 non-zero 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 non-numeric string as having a zero numeric value. For further details, refer to String-to-Number Conversion.

You can combine multiple Boolean logical expressions by using logical operators. Like all InterSystems IRIS expressions, they are evaluated in strict left-to-right order. There are two types of logical operators: regular logical operators (& and !) and short-circuit 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 short-circuit 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 time-consuming expression evaluations.

Some commands allow you to specify a comma-separated 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 short-circuit 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 short-circuit 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 comma-separated arguments. The comma is not a logical operator, but has the same effect as specifying the short-circuit && 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 String-to-Number Conversion. ObjectScript provides the following arithmetic operators:

Unary Positive (+)

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 well-formed numeric (or it returns 0 if no such interpretation was possible). For example:

USER>WRITE + "32 dollars and 64 cents"
32

For details, see the Unary Positive (+) reference page.

Unary Negative (-)

The unary negative operator (-) reverses the sign of a numerically interpreted operand. For example:

USER>SET x = -60
 
USER>WRITE x
-60
USER>WRITE -x
60

ObjectScript gives the unary negative operator precedence over the binary (two-operand) arithmetic operators.

For details, see the Unary Negative (-) reference page.

To return the absolute value of a numeric expression, use the $ZABS function.

Addition (+)

The addition operator adds two numeric values. For example:

USER>WRITE 2936.22 + 301.45
3237.67

For details, see the Addition (+) reference page.

Subtraction (-)

The subtraction operator subtracts one numeric value from another. For example:

USER>WRITE 2936.22 - 301.45
2634.77

For details, see the Subtraction (-) reference page.

Multiplication (*)

The multiplication operator multiplies two numeric values. For example:

USER>WRITE 9 * 5.5
49.5

For details, see the Multiplication (*) reference page.

Division (/)

The division operator divides one numeric value with another. For example:

USER>WRITE 355 / 113
3.141592920353982301

For details, see the Division ( / ) reference page.

Integer Division ( \ )

The integer operator divides one numeric value with another and discards any fractional value. For example:

USER>WRITE 355 \ 113
3

For details, see the Integer Division ( \ ) reference page.

Modulo (#)

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:

USER>WRITE 37 # 10
7
USER>WRITE 12.5 # 3.2
2.9

For details, see the Modulo (#) reference page.

Exponentiation (**)

The exponentiation operator raises one numeric value to the power of the other numeric value. For example:

USER>WRITE 9 ** 2
81

For details, see the Exponentiation (**) reference page. Exponentiation can also be performed using the $ZPOWER function.

Note:

InterSystems IRIS supports two representations of numbers: ObjectScript decimal floating-point (referred to as decimal format) and IEEE double-precision binary floating-point (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 String-to-Number Conversion.

Numeric relational operators should not be used to compare non-numeric strings.

ObjectScript provides the following numeric relational operators:

Less Than Operator (<)

The less than operator tests whether the left operand is less than the right operand. For example:

USER>WRITE 9 < 6
0

For details, see the Less Than (<) reference page.

Greater Than Operator (>)

The greater than operator tests whether the left operand is greater than the right operand. For example:

USER>WRITE 15 > 15
0

For details, see the Greater Than (<) reference page.

Less Than or Equal To Operator (<= or '>)

The less than or equal to operator tests whether the left operand is less or equal to than the right operand. For example:

USER>9 <= 6
0 

See the Less Than or Equal To (<= or '>) reference page.

Greater Than or Equal To Operator (>= or '<)

The greater than or equal to operator tests whether the left operand is greater than or equal to the right operand. For example:

USER>WRITE 15 >= 15
1

See the Greater Than or Equal To (<= or '>) reference page.

Note:

InterSystems IRIS supports two representations of numbers: ObjectScript decimal floating-point (referred to as decimal format) and IEEE double-precision binary floating-point (referred to as $DOUBLE format, generally used for special purposes).

Less-than/greater-than 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 left-to-right 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 (')

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:

USER>SET x=0

USER>WRITE 'x
1

See the Not (') reference page.

And (& or &&)

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).

For example.

USER>SET A=-4,B=1
 
USER>WRITE A&&B
1

See the And (& or &&) reference page. Also see the Not And (NAND) ('&) reference page.

Or (! or ||)

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).

For example:

USER>SET A=5,B=7

USER>WRITE A!B
1
USER>WRITE A||B
1

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.

For example:

USER>WRITE "Example "_"for "_"concatenation"
Example for concatenation

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:

Equals (=)

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:

USER>WRITE "SEVEN" = "SEVEN"
1
USER>WRITE "SEVEN" = "seven"
0
USER>WRITE "SEVEN" = " SEVEN "
0
USER>WRITE 07 = "07"
0

For details, see the Equals (=) reference page. Also see the Not Equals ('=) reference page.

Contains ([)

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:

USER>SET L="Steam Locomotive"

USER>SET S="Steam"

USER>WRITE L[S
1

For details, see the Contains ([) reference page. Also see the Does Not Contain ('[) reference page.

Follows (])

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:

USER>WRITE "LAMPOON"]"LAMP"
1

For details, see the Follows (]) reference page. Also see the Not Follows (']) reference page.

Sorts After (]])

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:

USER>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 a couple of strings to see if they are valid U.S. Social Security Number:

USER>SET test1="123-45-6789"

USER>SET test2="123-XX-6789"

USER>WRITE test1 ? 3N1"-"2N1"-"4N
1
USER>WRITE test2 ? 3N1"-"2N1"-"4N
0

For pattern syntax and other details, see the Pattern Match (?) reference page.

Note:

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.

Note:

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.

FeedbackOpens in a new tab