Swift traditionally pays great attention to syntax clarity and allows for the creation of custom operators (operator overloading), including new symbols and even keywords. This expands the capabilities of DSL and allows for very expressive code.
Without understanding the principles of operator declaration, one can produce ambiguous, poorly readable, and hard-to-maintain code. Incorrectly chosen precedence or associativity will lead to unexpected results. The compiler allows creating quite "dangerous" expressions if restrictions are not specified.
You can declare new infix, prefix, postfix operators, specify their priorities, and areas of usage. Example:
infix operator ~> : AdditionPrecedence func ~> (lhs: Int, rhs: Int) -> Int { return lhs * 10 + rhs } let x = 2 ~> 3 // 23
For custom priorities, you need to declare:
precedencegroup MyPrecedence { associativity: left higherThan: AdditionPrecedence } infix operator *** : MyPrecedence
Key features:
Is it mandatory to implement both a function and an operator declaration?
Yes, if you declare an operator, you need to implement the corresponding function - otherwise, it will result in a compiler error. Functions have a signature that matches the operator signature.
How to correctly choose precedencegroup, and how does it affect computation order?
precedencegroup specifies the computation priority and associativity for infix operators. An incorrect choice of group can lead to unexpected results in expressions with multiple operators (e.g., multiplication/addition and your custom operator).
Can a custom operator be declared with a text name?
No, custom operators are only available through special symbols or sequences defined by Swift's syntax. Text standard names are not allowed for operator declaration.
In the project, operators <<< and >>> were declared for strange transformations of collections, without description of priority, associativity, and documentation. New employees did not understand what they were doing and in what order the expressions were evaluated.
Pros:
Cons:
In the project, a custom operator => was used for declarative assembly of a chainable pipeline (for example, in a UI builder), with a clearly described priority and documented implementation. Every developer understood what they were doing and how it was used.
Pros:
Cons: