LSPS documentation logo
LSPS Documentation
Operators

Operators are symbols that cause a particular action, for example, comparison of values, summing up, assignment, etc.

Arithmetic Operators

Arithmetic operators are used on Integer and Decimal values similarly to their use in algebra.

Operator Description Example Result Note
+ addition 2 + 2 4
- subtraction 3 - 1 2
++ increment by 1intVar++ or ++intVarpostfix: returns value; then increments by one and assigns it to the referenced object (2++); prefix: increments value by 1 and reassigns it to the referenced object
-- decrements by 1intVar++ or ++intVarpostfix: returns value; then decrements by one and assigns it to the referenced object (2++); prefix: decrements value by 1 and reassigns it to the referenced object
* multiplication3 * 3 9
/ division 9 / 3 3
% modulo 10 % 31
** exponentiation3 ** 327 Since expressions are evaluated primarily in the left-to-right manner unless precedence or association rules take over, the expression 2**3**4 is evaluated as 2^3^4^^; the exponent follows the ** operator

Assignment Operator

To assign a value to use the assignment operator :=:

//assign value 1 to x:
int x := 1

Logical Operators

Logical operators are used to combine multiple expressions that each return a boolean value. Combination of expressions with logical operators return a single boolean value.

Operators and their return values

and, && (conjunction)

true if both operands are true; otherwise false

or, || (inclusive disjunction)

true when at least one of the operands is true; otherwise false

xor, exclusive disjunction

true when the operands value is not identical, that is one operand is true and the other operand is false; otherwise false

not or ! (negation)
true if the operand is false; false if the operand is true (unary operator)

Truth Table

Operand A Operand B A and B A or B A xor B not A
true true true true false false
true false false true true false
false true false true true true
false false false false false true

Since logical expressions are evaluated from left to right, the short-circuit evaluation is applied on and and or expressions:

  • for and expressions:<false> and <not_evaluated> evaluates to false
  • for or expression <true> or <not_evaluated> evaluates to false

Comparison Operators

Comparison operators serve to compare two values. Comparing returns a boolean value.

To compare two values, you can use the following operators:

  • = or == (equal) and != (not equal, alternatively noted as <>) check if the values of any data type are equal.
    def String varA:="value"
    def String varB:="value"
    varA=varB
    //returns true

    Note: When comparing records, it is the object identity that is compared, not the record value. Analogously, on shared records, the record IDs are compared. However, on non-shared records, you can define fields or relationships so that the values of these are used when comparing records (refer to the Record Fields in the GO-BPMN Modeling Language Guide).

  • < (lesser), > (greater), <= (lesser or equal), and >= (greater or equal) check if values of decimals, integers, and strings are lesser, lesser or equal, greater, or greater or equal and returns true or false.

    When comparing Strings, they are compared lexicographically as per Java lexicographic ordering of strings, for example, "Čapek" > "Hemingway" and "Čapek" > "Asimov" are true.

  • like searches for an occurrence of a pattern in a string

    The operator supports the wildcards ? for one character and * for one or multiple characters

    "matching exactly THIS word" like "* ??????? THIS *"
    
  • <=> (the spaceship operator): checks if values are lesser, equal, or greater and returns -1 if the left operand is lesser than the right operand, 0 if the left operand and right operand are equal, and 1 if the left operand is greater than the right operand.

    Applicable to the String, Decimal, Integers, and Date types (Date is a complex data type defined in the Standard Library)

    person1.name <=> person2.name

Concatenation

To concatenate two Strings, use the + concatenation operator.

varStringA+"String literal"

The String concatenation operator + can concatenate also a String and any subtype of the Object type: the Object type is converted to the appropriate String value and concatenated with the String; for example, a Date value is converted to a human readable date representation when concatenated with a string. Note that the String object must come first in such expressions.

String concatenation example If the first operands of the + operator is a string, the + operator is considered automatically the operand of concatenation and the non-string operand is automatically converted to a string.

"Timestamp: " + date("2014-07-31", yyyy-MM-dd)
//The date() function uses the DateTimeFormat implementation of the joda library (http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html) and returns a Date object;
//the function is evaluated as if wrapper in toString: toString(date("2014-07-31", yyyy-MM-dd))

Resulting string:

Timestamp: Thu Jul 31 00:00:00 CEST 2014

Note: If you want to keep a non-string operand before the string operand in concatenation, start your expression with the empty String literal "", for example, "" + author.surname + ", " + author.firstname.

Reference and Dereference Operators

The reference operator & returns Reference to a variable or a property path from a variable in the context of the variable. The dereference operator * takes a Reference value and returns the value currently stored in the referenced variable or property.

//instantiates record c1 with c1.name "Walter White":
def Partner c1 := new Partner(name -> "Walter White");
 
//reference variable ref with reference c1.name (current value "Walter White"):
def Reference<String> ref := &c1.name;
 
//variable x assigned dereferenced ref, that is "Walter White":
def String x := *ref;
 
//c1 assigned a new record instance with the name "Jesse Pinkman":
c1 := new Partner(name -> "Jesse Pinkman");
 
//new variable y assigned the dereferenced ref value (that resolves to "Jesse Pinkman"):
def String y := *ref;
 
//note that the value held by x remains "Walter White"

In the example the variable part is c1 and the property part is .name. To acquire the value of a reference, use the dereference operator *.

References hold the referenced expression and the associated context. In our example the referenced expression is c1.name.

Inclusion Operator

The inclusion operator in checks if an element is in a set or list.

The check returns the String "1 is in mySet" if 1 is in mySet.

if 1 in mySet
then "1 is in mySet"
end

Namespace Operator

The module namespace operator (::) is used to refer to elements of other module namespaces.

Consider ModuleA with a variable var imported into ModuleB. You can access var from ModuleB as follows:

ModuleA::var

The mechanism of module import is described in the GO-BPMN Modeling Language Specification.

Selector Operator

To access items in collections or maps, use the selector operator [] to specify the element to be returned:

on sets

name_of_set[element_position]

on lists

name_of_list[element_position]

Note that the first element of a List is on position zero. For example, [10,20,30][1] returns 20.

on maps

name_of_map[element_key]

Ternary Conditional

The ternary conditional operator ?: enables you to define a condition and two expressions. If the condition evaluates to true the first expression is returned. If the condition evaluates to false, the second expression is returned.

With the operator you can write the expression

if <CONDITION> then <EXPRESSION_1> else <EXPRESSION_2> end

as

<CONDITION> ? <TRUE_EXPRESSION> : <FALSE_EXPRESSION>

Null-Coalescing Operator

The null-coalescing operator ?? is a more effective version of if <expression_1> != null then <expression_2> with <expression_1> evaluated only once.

<expression_1> ?? <expression_2>;
//is equivalent to:
if <expression_1> != null then
   <expression_1>
else
   <expression_2>
end

Example:

def String title := getTitle() ?? "Default Title";

Access Operator

The dot operator . serves to access fields of a Record, possibly via relationships. Example:

<EXPRESSION>.<FIELD>

For example:

book.title

Note that the dot operator . fails with an exception if the <EXPRESSION> with the access operator is null. Use the safe-dot operator to prevent the exception.

Safe-Dot Operator

To prevent the system from raising an exception when it attempts to access a record field of a record which is null, use the safe-dot operator ?..

Similarly to the dot operator, the ?. operator serves to access Record Fields, possibly of related Records. Unlike the dot operator, no exception is raised when the record is null. The expression simply returns null.

<expression>?.field

Example:

def Person person := null;
//returns null without an error:
person?.email;
//you can also chain the access requests:
person?.contact?.operator?.operatorCallCode

Operator and Chaining Precedence

Generally, expression are evaluated from left to right.

Mathematical operators, logical, and relational operators follow their natural operator precedence:

  1. unary before multiplicative before additive and
  2. negation before relational before equality before exclusive disjunction before conjunction before disjunction.

Parentheses override operator precedence and the expression in parenthesis is evaluated as a whole.

Operator precedence order

  1. :: (scope operator)
  2. [] (selector), () (function/closure call), . (dot operator), ?. (safe dot operator)
  3. +, -, & (reference), * (dereference)
  4. ?? (ifnull)
  5. * (multiplication), / (division), % (modulo), ** (exponentiation)
  6. + (addition), - (subtraction)
  7. <, >, <=, >=, <=>
  8. = and == (equal), != (not equal), <>, like, in (inclusion)
  9. cast, as
  10. not and ! (negation)
  11. and and && (conjunction)
  12. or and ||, xor (disjunctions)
  13. ?: (ternary if)
  14. := (assignment)
  15. ; (chaining operator)

Evaluation Order

The order of expression evaluation at runtime is generally from left to right, that is, first the left-hand operand is evaluated and only then the right-hand operand is evaluated. Note that operator precedence can influence the evaluation order.

Chaining Expressions

To chain multiple expression, divide them with a semi-colon or a new line. A chained expression returns the return value of the last expression in the chain. Intermediary return values of the other chained expressions are ignored.

def String varString; varString := "Hello" //two expressions chained by a semi-colon (;)
varString:=varString + "World" //an expression chained by a new line