4. Operators

S2 operators have the following associativity and precedence, listed from highest precedence to lowest.

left Terms (literals, expressions in parentheses, variables, function/method calls, named unary operators)
nonassoc ++ --
left instanceof isa as
right not -
left * / %
left + -
nonassoc < > <= >=
nonassoc == !=
left and
left or
nonassoc ..
nonassoc ? :
right =

4.1. Arithmetic Operators

The S2 language has the usual set of arithmetic operators you'd expect to find in a programming language. These are the same as the arithmetic operators in perl.

As you might expect, these operators can only be applied to integers, and will return integers.

+ binary Addition
- binary Subtraction
* binary Multiplication
/ binary Division
% binary Modulus (remainder)
++ unary Increment in-place
-- unary Decrement in-place
- unary Negation

4.2. Comparison Operators

These operators allow you to compare one value to another. Both operands must be of the same type, and all but simple equality/inequality can only be applied to integers. Only primitive types may be compared with these operators. All comparison operators return a boolean value.

== binary Equals
!= binary Does not equal
< binary Less than
> binary Greater than
<= binary Less than or equal to
>= binary Greater than or equal to

4.3. Logical Operators

These operators perform logical operations on boolean values. All operands must be boolean, and a boolean value results.

and binary Logical AND
or binary Logical OR
not unary Logical complement

In summary, AND returns true if and only if both of its operands are true. OR returns true if one or both of its operands are true. NOT returns true if its operand is false, and false otherwise.

The two binary logical operators are usually used in an if statement to include two or more comparisons.

4.4. Type Conversion/Testing Operators

These functions operate on object values only. Their left operand is the subject, while the right operand is a class name.

isa Returns true if the object can be typecasted to the given class
instanceof Returns true if the type of the object is exactly the classname given.
as Cast the given value to the classname given, but only if the object's runtime type is compatible. If not, returns a null object.

The S2 language uses dynamic binding, which means that an object's type may be a subclass of the class of the variable which holds it. These functions allow the programmer to test the runtime type and, assuming the runtime type is compatible, convert (or cast) to a different variable type.

When calling methods on an object, it is the type of the object which determines which function will be called, not the type of the variable on which the arrow operator is applied.

4.5. Other Operators

These operators don't really fit into a category of their own, and have perhaps non-obvious functions.

4.5.1. The assignment operator: =

The assignment operator (which should not be confused with the equality test operator, ==), is used to assign a value to a named variable. This means that unlike most other operators, its left operand must be a variable name. No other kind of expression will do.

The assignment operator can take operands of any type, but the right-hand operand must be of the same type as the variable given on the left, or coercable into that type.

The assignment operator also returns whatever value it has just assigned to the variable, meaning that you can chain several assignments together as follows:

$foo = $bar = $baz = 2;

In this case, $foo, $bar and $baz will all be assigned the value 2.

As a special case, assignment can also be used when declaring local variables:

var string $name = "John";

However, this is only true for local variables. Class variables cannot be initialized in this way.

The symbol = is used for several other assignment-like things in the S2 language, including setting property values and layerinfo. These aren't really assignment, but act similarly and in the case of property setting follow many of the rules described above.

4.5.2. String Concatenation with +

The + symbol actually has two purposes in the S2 language. When one of its operands is a string, it becomes the string concatenation operator. In this form, it will firstly attempt to coerce any non-string operand into a string, then stick the two strings together to form a resulting string which is returned.

The simplest form of string concatenation involves two strings. In this case, both strings are just concatenated and that is it. However, as long as one operand remains a string, the other operand can be an integer, a boolean or an object with certain conditions. Objects may only be concatenated to strings if their class has an as_string() method which returns a string. The return value of this method will be used as the string value for concatenation.

String literals with interpolated variables are really just concatenation with a more convenient syntax, which is why you are able to interpolate integers and certain objects directly into string literals.

4.5.3. The ternary conditional operator ? :

This is the only operator in the S2 language with three operands. Its function can be thought of as being like an if statement in the form of an operator.

This operator is best explained with an example:

$label = ($c == 1 ? "1 comment" : "$c comments");

In this example, the conditional operator and its operands are enclosed in parenthesis for clarity. These are optional, but can make things more readable. The first operand, preceding the question-mark symbol, is a boolean expression. In this case it is an equality test. If this expression evaluates to true, the second operand, which is after the question-mark and before the colon, is returned. If the expression is false, the third operand is returned.

The first operand must be a boolean expression. The second and third operands can be of any type but their types must match. The return type of this operator is the same as that of the second and third operand. In the above example, then, the return type would be string.

In all cases an if construct can be used in place of this operator, but the conditional operator is shorter and more readable in some cases.

4.5.4. The range operator ..

This rather quirky operator is borrowed from Perl. It takes two integer operands and returns an array of integers containing all integers between the first and second operand, inclusive. For example:

var int[] list = 1 .. 10;

The array $list will now contain ten elements, each numbered in order from 1 to 10. This has the same effect as:

var int[] list = [1,2,3,4,5,6,7,8,9,10];

This operator is really only useful for creating a loop which will iterate a certain number of times:

foreach var int i (1 .. 10) { println "Iteration number $i"; }

This example will print ten lines, each containing a number from 1 to 10 in order.

Note

Some readers will probably balk at the use of an array of integers to create a loop such as this, as it would use more memory than a conventional for loop from a general programming language.

However, you don't have to worry. The above idiom is optimised to an efficient form at compile time, so there is no memory wasted.

4.6. Named Unary Operators

The following are the built-in named operators. You do not have to wrap the following term in parentheses.

isnull $object
returns a boolean: true if $object is null (has no value)
defined $object
opposite of isnull. might be prettier than negating isnull
new ClassName
returns an instance of ClassName with all members empty or zero
null ClassName
returns an undefined value of type ClassName
reverse $string
returns copy of $string with characters reversed
reverse $array
returns shallow copy of $array with elements reversed.
size $string

returns number of bytes in $string. This behavior is deprecated. Please see note below.

size $array
returns number of elements in $array

Note

The use of the size operator on strings is deprecated and will be removed or updated without notice. Instead, you should use the string class's length method to get the number of characters. Remember that some characters are represented by more than one byte.