If atomic values are the building blocks of expressions then operators are the cement. With operators you can perform arithmetic, make comparisons and assign new values to variables. from them.

Operator Precedence

Operator precedence is used to resolve ambiguities in an expression. Each operator has a precedence level which determines its priority in an expression. For example, the expression 12 + 3 * 4 parses as though it were 12 + (3 * 4) and not as (12 + 3) * 4 because multiplication has higher precedence than addition.

Table 6.1. Operator Precedence Table

Precedence Operators Description
Highest () Parenthesis
  Function/method calls, new Function calls (see Function Calls), object creation (see new)
  ++, -- Postfix increment/decrement (see Increment/Decrement)
  ++, --, +, - Prefix increment/decrement (see Increment/Decrement), unary sign change
  (int), (double), (string), (boolean), ! Type Casts, logical not (see Logical Operators)
  *, /, % Multiplication/division (see Arithmetic Operators)
  +, - Addition/substraction (see Arithmetic Operators)
  <, <=, >, >= Numerical or string comparisons (see Comparison Operators)
  ==, != Equality comparisons (see Comparison Operators)
  && Logical and (see Logical Operators)
  || Logical or (see Logical Operators)
Lowest =, +=, -=, *=, /=, %=, Assignment Operators

The new Operator

The new operator is used to create instances of object type variables. Currently the only object in RSP that can be created with new is the Connection object.

The syntax is new ObjectType(arguments...). It calls a special method of the object being created called the constructor. The arguments required by the constructor will depend on the object, but the parenthesis are required even if no arguments are needed.

Increment and Decrement Operators

The ++ (increment) and -- (decrement) operators are used in expressions to increment or decrement an lvalue - either an int or a double.

If used as a prefix then the increment/decrement will be carried out before the rest of the expression is evaluated, otherwise it is carried out after the expression is evaluate. If there are multiple prefix operators or multiple postfix operators in an expression then no guarantee can be made about the order in which they will execute.

Example 6.1. Increment/Decrement Example

int i = 42;

i++;    // i = 43
--i;    // i = 42;

// j becomes 42, i becomes 43 (increment occurs after the expression)
int j = i++;

// i becomes 42, then j is assigned the value of i
j = --i;

Type Casts

Use type casts to convert one type of variable to another. The table below shows the data types that can be legally cast.

Table 6.2. Type Conversion Table

  From int From double From boolean From string
To int No effect. The value is rounded down. true becomes 1, false becomes 0. If the string consists of decimal digits then it will be converted to an integer value. Otherwise the result is 0. The string may be prefixed with "-" to denote a negative number.
To double No effect. No effect. true becomes 1.0, false becomes 0.0. If the string follows the same lexical pattern as a double then it will be converted to a double. Otherwise the result is undefined but probably zero (it will not be a run time error).
To boolean A nonzero value becomes true, a value of zero becomes false. A nonzero value becomes true, a value of zero becomes false. No effect. The following strings get converted to true, where the test is case insensitive:
  • "1"
  • "Y"
  • "Yes"
  • "T"
  • "True"
Any other string produces a value of false.
To string The integer is converted to its decimal string representation. The double is converted to its string representation. true becomes "True", false becomes "False". No effect.

Example 6.2. Type Casts Example

int i = (int)42.0;
double j = (double)i;
string s = (string)i;
boolean b = (boolean)"True";

Arithmetic Operators

The arithmetic operators perform basic arithmetic on numerical types. Note that you cannot mix integers and doubles in arithmetic expressions without using type casts.

The + operator can also be used for string concatention. Any basic type can be concatenated to a string.

Example 6.3. Arithmetic Example

int i = 42 + 3 * 7;
int modulo = 17;
int remainder = i % modulo;

string str1 = "An " + "example " + "of " + "string " + "concatenation!"
string str2 = "The remainder is " + remainder;

Comparison Operators

The equality operators == and != are used to determine if two values are equal or not equal respectively. The left and right hand sides must be of the same type, and may not be object references or arrays (although array elements are allowed).

The comparison operators <, <=, > and >= are used for numerical and string comparisons. The left and right hand sides must be of the same type and may be either integers, doubles or strings. String comparisons are done lexiographically and are case sensitive.

The result type of a comparison expression is always a boolean.

Example 6.4. Arithmetic Example

12 < 42;            // true
"Hello" < "Golf";   // true
"Hello" == "hello"; // false
"Hello" != "hello"; // true

Logical Operators

Logical operators operate on boolean values only. The logical not (!) unary operator returns the complement of a boolean value. The operators && and || perform logical 'and' and 'or' respectively.

RSP uses shortcut semantics for its logical operators. This means that if the left hand side of an && operator evaluates to false then the right hand side will not be evaluated because it is already certain that the result of the operator will be false. Similarly if the left hand side of an || operator is true then the result will be true without evaluating the right hand side.

It is important to understand shortcut semantics because it has relevance when the right hand side expression has a side effect. For example, it may be a function call. If it is not evaluated then the function will never be called.

Example 6.5. Logical Operators Example

if(i == 42 && str == "Hello")
    // . . .
else if(i == 17 || str == "Boo")
    // . . .
else if(!(i == 7))
    // . . .

// The function calls here never get made because of shortcut semantics
true || func_call();
false && func_call();

Assignment Operators

Use the assignment operators to assign new value to variable references. The left hand side of an assignment operator must be an lvalue.

The value of an assignment expression is the new value of the variable being assigned. In the case of the basic assignment operator = this will be the same as the right hand side. The other assignment operators combine an assignment with the arithmetic.

Example 6.6. Assignments Example

int num, a, b, c;
string str;

// Simple assignment
num = 42;
str = "Hello";

// Chained assignment - a, b, c and num now all equal 48
a = b = c = num += 6;

// More arithmetic
num /= 6;           // num = 8
num -= 4;           // num = 4
num *= 3;           // num = 12
num += num;         // num = 24

// And with strings
str += ", world!";