Home Did you know you can create your own operator in Swift? 😲
Post
Cancel

Did you know you can create your own operator in Swift? 😲

Introduction

Swift is a powerful and flexible programming language that provides developers with a wide range of tools and features to express their ideas and solve complex problems. One of the lesser-known but fascinating capabilities of Swift is the ability to create custom operators. While Swift comes with a rich set of built-in operators, being able to define your own operators can significantly enhance the readability and expressiveness of your code.

What are we even talking about

So, what exactly is an operator? In programming, an operator is a symbol that represents a specific operation, such as addition, subtraction, or comparison. Operators allow us to manipulate data and perform calculations. Swift has a comprehensive set of operators for arithmetic, logical, and bitwise operations, among others.

Alright, Show me the magic

Creating a custom operator in Swift is a straightforward process. You can define your own operators using special characters or combinations of existing operators. The first step is to declare the operator using the operator keyword, followed by the operator itself and any attributes associated with it. Here’s an example of a custom operator that adds two integers and returns their sum:

1
2
3
4
5
infix operator +++

func +++(lhs: Int, rhs: Int) -> Int {
    return lhs + rhs
}

In this example, we define the +++ operator as an infix operator, which means it is placed between its operands. The operator takes two integers (lhs and rhs) and returns their sum. Now, we can use the +++ operator just like any other built-in operator:

1
2
let result = 5 +++ 3
print(result) // Output: 8

Custom operators can also have different associativity and precedence. Associativity determines how operators of the same precedence are grouped together, either left-to-right (left) or right-to-left (right). Precedence defines the order of evaluation when multiple operators are used together. You can specify these attributes when declaring your custom operator, just like you would with built-in operators:

1
2
3
4
5
6
7
8
9
10
11
infix operator +++: AdditionPrecedence
infix operator **: MultiplicationPrecedence

func **(lhs: Int, rhs: Int) -> Int {
    return lhs * rhs
}

func +++(lhs: Int, rhs: Int) -> Int {
    return lhs + rhs
}

In this example, we define the ** operator as an infix operator with the MultiplicationPrecedence attribute. This ensures that the ** operator has higher precedence than the +++ operator defined earlier. Now, we can use both operators together, and Swift will apply the correct precedence rules:

1
2
let result = 2 ** 3 +++ 4
print(result) // Output: 10

By specifying the precedence groups for custom operators using attributes like AdditionPrecedence and MultiplicationPrecedence, you ensure that the custom operators follow the same precedence rules as the built-in operators. This helps maintain consistency and predictability in the evaluation of expressions involving custom operators.

It’s worth noting that Swift provides several other predefined precedence groups for different types of operators, such as ComparisonPrecedence for comparison operators (<, >, ==, etc.) and LogicalConjunctionPrecedence for logical conjunction operators (&&). These predefined precedence groups help ensure that expressions are evaluated in a logical and intuitive manner.

One more thing

I don’t want you to leave this article with the impression that infix operators are the only possible custom operators that we can create, besides infix operators, Swift supports two other kinds of operators: prefix and postfix operators.

  1. Prefix Operators:

Prefix operators are placed before their operands. They are unary operators that perform an operation on a single operand. Some examples of prefix operators in Swift include the negation operator - and the logical negation operator !. Here’s an example of a custom prefix operator:

1
2
3
4
5
6
7
8
9
prefix operator 

prefix func (number: Double) -> Double {
    return sqrt(number)
}

let result = 25.0
print(result) // Output: 5.0

In this example, we define a custom prefix operator √ that calculates the square root of a number. The √ operator is then used with the operand 25.0 to calculate the square root, resulting in the output of 5.0.

  1. Postfix Operators:

Postfix operators are placed after their operands. Similar to prefix operators, they are unary operators that operate on a single operand. However, postfix operators have lower precedence than both infix and prefix operators. Here is an example of a custom postfix operator:

1
2
3
4
5
6
7
8
9
postfix operator ++

postfix func ++(number: inout Int) {
    number += 1
}

var numberFive = 5
numberFive++
print(numberFive) // Output: 6

In this example, we define a custom postfix operator ++ that increments an integer value by 1. The ++ operator is used as a postfix operator with the operand numberFive. After the operation, the value of numberFive is incremented by 1, resulting in the output of 6 when it is printed.

It’s important to note that the use of postfix operators should be approached with caution. The increment and decrement operators (++ and --) are already provided as built-in postfix operators in Swift. Creating additional postfix operators can potentially lead to confusion and make the code less readable. Therefore, it’s recommended to use postfix operators judiciously and consider their impact on code clarity.

:Creative example of postfix operator:

1
2
3
4
5
6
7
8
9
postfix operator ❗️

postfix func ❗️(word: String) -> String {
    return word.uppercased() + "!"
}

let message = "hello"
let modifiedMessage = message❗️
print(modifiedMessage) // Output: HELLO!

Conclusion

Creating custom operators can be a powerful tool for domain-specific languages or to make your code more expressive and self-explanatory. However, it’s essential to use custom operators judiciously and ensure they don’t lead to confusion or obscure the intent of your code. It’s generally recommended to reserve custom operators for situations where they provide a clear benefit in terms of readability and comprehension.

In addition to defining your own operators, Swift also allows you to extend existing types with new functionality. This means you can add custom operators to existing types, such as adding a new operator for concatenating strings or performing custom operations on arrays.

So, next time you find yourself struggling to express a concept with existing operators, consider creating your own operator in Swift. You might be surprised by the clarity and elegance it brings

This post is licensed under CC BY 4.0 by the author.