Everything About Operators in Swift

Creating Custom Operators in swift:

Leela Prasad
Swift India
11 min readFeb 21, 2019

--

Basic Operators, Overflow Operators, Advanced Operators, Range Operators, Custom Operators.

You will learn everything about operators in swift in this tutorial. It is very easy to work with these, as we can use them for advanced use cases with our types(model objects) in the projects.

You can read basic introduction here, but it is not required to understand this tutorial.

→ Terminology :

An operator is a special symbol or phrase that you use to check, change, or combine values. The values that operators affect are operands. In the expression “2 + 4 = 6” the “+”symbol is a binary operator and its two operands are the values 2 and 4.

Operators are unary, binary, or ternary:

  • Unary : Unary operators operate on a single target (such as +1). Unary prefix operators appear immediately before their target (such as !b), and unary postfix operators appear immediately after their target (such as c!).
  • Binary : Binary operators operate on two targets (such as 3 + 5) and are infix because they appear in between their two targets.
  • Ternary : Ternary operators operate on three targets. Like C, Swift has only one ternary operator, the ternary conditional operator (a ? b : c).

Note : Here I mention all the operators with examples. For simple ones, there is no explanation but example. If you want to read more about them, just follow the links which are provided at the bottom of this tutorial.

→ Basic Operators :

  • Assignment Operator

The assignment operator (a = b) initialises or updates the value of “a” with the value of “b”.

  • Arithmetic Operators

Swift supports the four standard arithmetic operators for all number types:

  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)
  • Remainder Operator

The remainder operator (a % b) works out how many multiples of b will fit inside a and returns the value that is left over (known as the remainder).

Ex:

9 % 4 // equals 1

-9 % 4 // equals -1

  • Unary Minus Operator

The sign of a numeric value can be toggled using a prefixed -, known as the unary minus operator. The unary minus operator (-) is prepended directly before the value it operates on, without any white space.

  • Unary Plus Operator

The unary plus operator (+) simply returns the value it operates on, without any change:

  • Compound Assignment Operators

Combining Assignment(=) operator with another operators.

  • Comparison Operators

Swift supports all standard C comparison operators. Each of the comparison operators returns a Bool value to indicate whether or not the statement is true.

  • Equal to (a == b)
  • Not equal to (a != b)
  • Greater than (a > b)
  • Less than (a < b)
  • Greater than or equal to (a >= b)
  • Less than or equal to (a <= b)

Example:

1 == 1 // true because 1 is equal to 1

2 != 1 // true because 2 is not equal to 1

2 > 1 // true because 2 is greater than 1

1 < 2 // true because 1 is less than 2

1 >= 1 // true because 1 is greater than or equal to 1

2 <= 1 // false because 2 is not less than or equal to 1

  • Ternary Conditional Operator

The ternary conditional operator is a special operator with three parts, which takes the form question ? answer1 : answer2. It’s 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.

Ex: hasEnoughMoney ? makePayment() : discardPayment()

  • Nil-Coalescing Operator

The nil-coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression bmust match the type that is stored inside a.

Ex:

var myLuckyNumber: Int?

var aNumber = myLuckyNumber ?? 007

in the above example, it evaluates first ‘myLuckyNumber’ variable, if it contains a value, it unwraps it and returns. In case if it has no value, it returns ‘007’ as its value. Here both types should match. You cannot use any-type other than Int, because ‘myLuckyNumber’ is of Int type.

→ Range Operators :

Swift includes several range operators, which are shortcuts for expressing a range of values.

  • Closed Range Operator

The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.

  • Half-Open Range Operator

The half-open range operator (a..<b) defines a range that runs from a to b, but doesn’t include b. It’s said to be half-open because it contains its first value, but not its final value. As with the closed range operator, the value of a must not be greater than b. If the value of a is equal to b, then the resulting range will be empty.

  • One-Sided Ranges

The closed range operator has an alternative form for ranges that continue as far as possible in one direction — for example, a range that includes all the elements of an array from index 2 to the end of the array. In these cases, you can omit the value from one side of the range operator. This kind of range is called a one-sided range because the operator has a value on only one side.

→ Logical Operators

Logical operators modify or combine the Boolean logic values true and false. Swift has 3 logical operators. They are;

  • Logical NOT (!a)

The logical NOT operator (!a) inverts a Boolean value so that true becomes false, and false becomes true. The logical NOT operator is a prefix operator, and appears immediately before the value it operates on, without any white space.

  • Logical AND (a && b)

The logical AND operator (a && b) creates logical expressions where both values must be true for the overall expression to also be true. If either value is false, the overall expression will also be false. In fact, if the first value is false, the second value won’t even be evaluated, because it can’t possibly make the overall expression equate to true. This is known as short-circuit evaluation.

  • Logical OR (a || b)

The logical OR operator (a || b) is an infix operator made from two adjacent pipe characters. You use it to create logical expressions in which only one of the two values has to be true for the overall expression to be true.

→ Identity Operators

Because classes are reference types, it’s possible for multiple constants and variables to refer to the same single instance of a class behind the scenes. It can sometimes be useful to find out whether two constants or variables refer to exactly the same instance of a class. To enable this, Swift provides two identity operators:

  • Identical to (===)
  • Not identical to (!==)

Advanced Operators

Swift provides several advanced operators that perform more complex value manipulation. Unlike arithmetic operators in C, arithmetic operators in Swift do not overflow by default. Overflow behavior is trapped and reported as an error. To opt in to overflow behavior, use Swift’s second set of arithmetic operators that overflow by default, such as the overflow addition operator (&+). All of these overflow operators begin with an ampersand (&).

→ Bitwise Operators

Bitwise operators enable you to manipulate the individual raw data bits within a data structure. They are often used in low-level programming, such as graphics programming and device driver creation. Bitwise operators can also be useful when you work with raw data from external sources, such as encoding and decoding data for communication over a custom protocol.

  • Bitwise NOT Operator

The bitwise NOT operator (~) inverts all bits in a number. The bitwise NOT operator is a prefix operator, and appears immediately before the value it operates on, without any white space.

  • Bitwise AND Operator

The bitwise AND operator (&) combines the bits of two numbers. It returns a new number whose bits are set to 1 only if the bits were equal to 1 in both input numbers.

  • Bitwise OR Operator

The bitwise OR operator (|) compares the bits of two numbers. The operator returns a new number whose bits are set to 1 if the bits are equal to 1 in either input number.

  • Bitwise XOR Operator

The bitwise XOR operator, or “exclusive OR operator” (^), compares the bits of two numbers. The operator returns a new number whose bits are set to 1 where the input bits are different and are set to 0 where the input bits are the same.

  • Bitwise Left and Right Shift Operators

The bitwise left shift operator (<<) and bitwise right shift operator (>>) move all bits in a number to the left or the right by a certain number of places. Bitwise left and right shifts have the effect of multiplying or dividing an integer by a factor of two. Shifting an integer’s bits to the left by one position doubles its value, whereas shifting it to the right by one position halves its value.

For these, shifting behaviours and rules are different for signed & unsigned integers. For clear explanation please check here.

→ Overflow Operators

If you try to insert a number into an integer constant or variable that cannot hold that value, by default Swift reports an error rather than allowing an invalid value to be created. This behavior gives extra safety when you work with numbers that are too large or too small. Providing error handling when values get too large or too small gives you much more flexibility when coding for boundary value conditions.

However, when you specifically want an overflow condition to truncate the number of available bits, you can opt in to this behavior rather than triggering an error. Swift provides three arithmetic overflow operators that opt in to the overflow behavior for integer calculations. These operators all begin with an ampersand (&):

  • Overflow addition (&+)
  • Overflow subtraction (&-)
  • Overflow multiplication (&*)

For both signed and unsigned integers, overflow in the positive direction wraps around from the maximum valid integer value back to the minimum, and overflow in the negative direction wraps around from the minimum value to the maximum. For clear explanation please check here.

Precedence and Associativity

Operator precedence gives some operators higher priority than others; these operators are applied first. Operator associativity defines how operators of the same precedence are grouped together, either grouped from the left, or grouped from the right. Think of it as meaning “they associate with the expression to their left,” or “they associate with the expression to their right.”

It is important to consider each operator’s precedence and associativity when working out the order in which a compound expression will be calculated. For example, operator precedence explains why the following expression equals 17.

→ 2 + 3 % 4 * 5

→ // this equals 17

If you read strictly from left to right, you might expect the expression to be calculated as follows:

  • 2 plus 3 equals 5
  • 5 remainder 4 equals 1
  • 1 times 5 equals 5

However, the actual answer is 17, not 5. Higher-precedence operators are evaluated before lower-precedence ones. In Swift, as in C, the remainder operator (%) and the multiplication operator (*) have a higher precedence than the addition operator (+). As a result, they are both evaluated before the addition is considered.

However, remainder and multiplication have the same precedence as each other. To work out the exact evaluation order to use, you also need to consider their associativity. Remainder and multiplication both associate with the expression to their left. Think of this as adding implicit parentheses around these parts of the expression, starting from their left:

→ 2 + ((3 % 4) * 5)

(3 % 4) is 3, so this is equivalent to:

→ 2 + (3 * 5)

(3 * 5) is 15, so this is equivalent to:

→ 2 + 15

This calculation yields the final answer of 17.

Operator Methods OR Operator Overloading

Classes and structures can provide their own implementations of existing operators. This is known as overloading the existing operators. In order to overload an operator, you have to implement a function whose name is the operator symbol.

Just have a look into the following example.

Custom Operators

You can declare and implement your own custom operators in addition to the standard operators provided by Swift. New operators are declared at a global level using the operator keyword, and are marked with the prefix, infix or postfix modifiers.

For new custom operators, you need to create the operator first. In the following example, ‘>>’ is used as a custom operator symbol, and its implementation is to perform multiplication with it self for every x, y and z values in the above Vector struct type. It is used as a prefix operator, so we declared with the prefix keyword. Implementation goes into the type, with type method, with the operator symbol as a method name.

  • Precedence and Associativity

All operators in Swift belong to a precedence group, which describes the order in which operators should be evaluated. A precedence group specifies an operator’s precedence relative to other infix operators, as well as the operator’s associativity. For full list of Precedence and associativity, please read here. Only infix operators need precedence & associativity. All custom infix operators each belong to a precedence group.

Note1 : You do not specify a precedence when defining a prefix or postfix operator. However, if you apply both a prefix and a postfix operator to the same operand, the postfix operator is applied first.

Note 2 : A custom infix operator that is not explicitly placed into a precedence group is given a default precedence group with a precedence immediately higher than the precedence of the ternary conditional operator.

Here, in the following example, observe the change in the result, when Precedence group changes. When ComparisonPrecedence applied, because it is lower than AdditionPrecedence, first addition takes place before the custom operation takes place.

You can create your own precedence group as well, like the following example.

Here, you create a new precedence group named MyCustomPrecedence. You place it lower than AdditionPrecedence, because you want addition to take precedence. You also make it left-associative because you want it evaluated from left-to-right as you do in addition and multiplication. Then you assign your >|< operator to this new precedence. In addition to lowerThan, you can also specify higherThan in your MyCustomPrecedence. This becomes important if you have multiple custom precedence groups in a single project.

— — — — — — — — — *********************** — — — — — — — — —

you can contact / follow me on twitter & linkedIn accounts.

Thanks for reading…

****************************!!!See you!!!****************************

--

--