Define Swift Operators

Assuming we have a vector struct here:

struct Vector {
var x: CGFloat
var y: CGFloat
}

Image we want to implement a function for vector addition, how could we do that? Of course we could define a function and put two vectors as parameters, but this is not a elegant way. The better solution might be using custom-defined operators.

Let’s get started to define one and use it for vector addition.


First, we need to declare an operator as a global variable. Two keywords are required: operator and prefix/infix/postfix . Here we use infix as the operation happens between two targets:

infix operator ★+

Note that custom operators can only begin with two types of characters.

  1. ASCII characters /, =, -, +!, *, %, <, >, &, |, ^?, or ~
  2. one of the Unicode characters defined in the grammar (which include characters from the Mathematical Operators, Miscellaneous Symbols, and Dingbats Unicode blocks, among others).

Here comes an interesting topic: if you define the operator with . as beginning, then it is valid to latter add with another . .

However, if the operator does not start with . , then there should be no dots afterwards; otherwise it will be regarded as two operators followed one by one, which is an incorrect definition.

infix operator .+.   // correct
infix operator +.+ // error: operator with postfix spacing cannot start a subexpression

Then we can define the specific precedence and associativity of the operator.

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.

Swift offers default precedence groups for this case, such as:

precedencegroup Equivalence {
associativity: left
higherThan: LogicalConjunctionPrecedence
lowerThan: ComparisonPrecedence
}

For more explanation please reference here.

Back to our vector addition case, luckily, we do not need to touch this. So let’s move forward.


Finally let us implement how to use this operator for vectors:

extension Vector {
static func ★+ (left: Vector, right: Vector) -> Vector {
return Vector(x: left.x + right.x, y: left.y + right.y)
}
}

Right now we have our own *+ operator. By making use of it, vector addition seems convenient and natural than the function implementaion:

let vector1 = Vector2D(x: 10, y: 20)
let vector2 = Vector2D(x: 30, y: 10)

let vector = vector1 ★+ vector2 // vector.x: 40, vector.y: 30

For more details, please reference Apple’s Advanced Operators and Lexical Structure.