Operators

An operator is a special symbol that you use to check, change or combine values. For example, the addition operator "+" adds two numbers.

10 + 7

The values that operators affect are called operands. In the example above, the + symbol is the operator, and its two operands are the values 10 and 7.

Operators are unary, binary or ternary depending on whether they require 1, 2 or three operands.

Assignment operator

The assignment operator assigns the value on its right hand side to the variable or property on its left hand side.

variable = 10
root.width = 102

The assignment operator does not return a value.

Arithmetic operators

Zing supports the four standard arithmetic operators for number types.

1 + 2           // equals 3
5 - 3           // equals 2
2 * 3           // equals 6
10 / 4          // equals 2.5

When you add, subtract or multiply two Int values, the result is always an Int, otherwise it is a Float. The result of a division is always a Float.

The addition operator is also supported for String concatenation.

"hello, " + "world"  // equals "hello, world"

Remainder operator

The remainder operator finds the largest whole number of multiples of the first operand that will fit into the second operand, and returns the value that is left over.

9 % 4           // equals 1

The remainder operator calculates the remainder term in the following equation:

left operand == right operand * multiplier + remainder

The remainder equation shows how the operator works for various combinations of positive and negative numbers.

 9 %  4     // equals  1  (9 ==  4 *  2 +  1)
-9 %  4     // equals -1  (9 ==  4 * -2 + -1)
 9 % -4     // equals  1  (9 == -4 * -2 +  1)
-9 % -4     // equals -1  (9 == -4 *  2 + -1)

If both the left and right operands are Ints, the result of the remainder operator is also an Int. Otherwise it is a Float.

Power operator

The power operator returns the left operand raised to the power of the right operand.

3 ^ 2           // equals 9
2 ^ 0.5         // equals 1.4142

The result of the power operator is always a Float.

Unary minus operator

The sign of a numeric value can by toggled using the unary minus operator.

var three = 3
var minusThree = -three
var plusThree = -minusThree

The result of the unary minus operator has the same type as its operand.

Unary plus operator

The unary plus operator returns the value it operators on without any change. Its only use is to provide symmetry in your code when also using the unary minus operator.

var minusSix = -6
var alsoMinusSix = +minusSix  // alsoMinusSix equals -6

The result of the unary plus operator has the same type as its operand.

Compound assignment operators

Compound assignment operators combine an assignment with an arithmetic operation.

a = 2
a += 3   // a is now equal to 5

There is a corresponding compound assignment operator for each binary arithmetic operator.

a += 3   // equivalent to a = a + 3
a -= 2   // equivalent to a = a - 2
a *= 4   // equivalent to a = a * 4
a /= 9   // equivalent to a = a / 9
a ^= 5   // equivalent to a = a ^ 5
a %= 7   // equivalent to a = a % 7

Compound assignment operators do not return a value.

Comparison operators

The comparison operators compare two operands, and return the boolean value true when the comparison is true and false when it is not.

Equality comparisons

The equality comparisons compare whether one value is exactly equal to another.

10 == 10   // True because 10 is equal to 10
10 != 11   // True because 10 is not equal to 11

The equality comparisons can compare any two operands of the same type.

Relational comparisons

The relational comparisons compare whether one value is less than or greater than another.

10 < 11    // True because 10 is less than 11
11 > 10    // True because 11 is greater than 10
10 <= 10   // True because 10 is less than or equal to 10
10 >= 11   // False because 10 is not greater than or equal to 11

The relational comparisons can compare two numeric operands or two string operands.

Ternary conditional operator

The ternary conditional operator is a special operator with three parts, which takes the following form

question ? answer1 : answer2

It is a shortcut for evaluating one of two expressions based on whether question is true or false. If question is true, it evaluates answer1 and returns its value; otherwise, it evaluates answer2 and returns its value.

The ternary operator is shorthand for the following pseudo code

if question {
    answer1
} else {
    answer2
}

The ternary conditional operator provides an efficient shorthand for deciding which of two expressions to consider. However, the ternary conditional operator should be used with care as it can lead to hard-to-read code if overused.

The code below demonstrates how you might use the ternary conditional operator in a property expression to set an item's height.

height: 60 + (header.visible ? header.height : 0)

Range operators

Zing includes two range operators, which are most useful for generating a numeric sequence as input to a for statement.

Closed range operator

The closed range operator creates a range spanning from the value of the left operand to the value of the right operand, inclusive of both values.

for var index in 1 ... 5 {
    System.log(index, "times 5 is", index * 5)
}

// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25

Both operands must be Ints.

Half-open range operator

The half-open range operator creates a range that runs from the value of the left operand to the value of the right operand, but does include the value of the right operand. It is said to be half open as it contains the value of the first operand, but not the value of the second.

Half-open ranges are particularly useful when you work with zero-based lists such as arrays, where it is useful to count up to (but not including) the length of the list.

var names = ["Bob", "Clair", "David", "Sarah"]
for var index in 0 ..< names.length {
    System.log("Person", index + 1, "is called", names[index])
}

// Person 1 is called Bob
// Person 2 is called Clair
// Person 3 is called David
// Person 4 is called Sarah

Both operands must be Ints.

Logical operators

Logical operators modify or combine the boolean logic values true and false. They are used most often as input to if and while statements.

Logical NOT operator

The NOT operator inverts a boolean value, such that true becomes false and false becomes true. The NOT operator appears immediately before the value it operates on.

var allowedEntry = false
if !allowedEntry {
    System.log("ACCESS DENIED")
}

// Logs "ACCESS DENIED"

As the NOT operator is a prefix operator, the production "if !allowedEntriy" is often read as "if not allowed entry".

Logical AND operator

The AND operator returns true if both its left and right operands are true, and false otherwise.

var hasDoorCode = true
var passedRetinaScan = false
if hasDoorCode && passedRetinaScan {
    System.log("Welcome!")
} else {
    System.log("ACCESS DENIED")
}

// Logs "ACCESS DENIED"

The AND operator short-circuits the evaluation of the right hand expression.

Logical OR operator

The OR operator returns true if either its left or right operands are true, and false otherwise.

var hasDoorKey = false
var hasPassword = true
if hasDoorKey || hasPassword {
    System.log("Welcome!")
} else {
    System.log("ACCESS DENIED")
}

// Logs "Welcome!"

The OR operator short-circuits the evaluation of the right hand expression.

Combining logical operators

You can combine multiple logical operators to create longer compound expressions.

if hasDoorCode && passedRetinaScan || hasDoorKey || hasPassword {
    System.log("Welcome!")
} else {
    System.log("ACCESS DENIED")
}

// Logs "Welcome!"

This example uses multiple && and || operators to create a longer compound expression. However, the && and || operators still operate on only two values, so this is actually three smaller expressions chained together.

The expression shown above can be read as "if we’ve entered the correct door code and passed the retina scan, or if we have a valid door key, or if we know the emergency password, then allow access".

It is sometimes useful to include parentheses when they are not strictly needed, to make the intention of a complex expression easier to read.

if (hasDoorCode && passedRetinaScan) || hasDoorKey || hasPassword {
    System.log("Welcome!")
} else {
    System.log("ACCESS DENIED")
}

// Logs "Welcome!"

Cast operator

The cast operator converts a reference to one element type to a reference of a different type.

expression cast ElementType

An expression that references a particular element type may actually refer to an instance of a more derived element behind the scenes. When you believe this is the case, you can try to downcast it using the cast operator.

Item item = …
(item cast Rectangle).color = #red

If the downcasting fails - because the expression does not refer to an instance target type - it will return a null reference. You can use this to test if the reference refers to an instance of the derived type.

if item cast Rectangle {
    …
}

This can be taken a step further by combining the cast, test and assignment into a single statement like this:

if var rect = item cast Rectangle {
    rect.color = #red
}

Precedence

The following table shows the precedence and associativity of operators.