# Swift – Custom Operators

This is an argument that I like a lot, the possibility to create or to override an operator changing its functionality. Let’s see a simple example just to convince you to use it!

###### Percentage calculation

Why don’t you use the percentage sign “%” to calculate the percentage?

What do you think of this:

`var fivePercent = 5% print( fivePercent ) // 0.05`

If you like it, you can continue reading!

## TL;DR

How works this percentage sign?

New operators are declared at a global level using the `operator` keyword, and are marked with the `prefix``infix` or `postfix` modifiers:

`prefix[postfix, infix] operator %`

This means that your new operator (%) can be used as:

• `postfix` like 5%
• `prefix` like %5
• `infix` like  2%5

as you prefer.

Example for percentage using POSTFIX:

`postfix operator % postfix func % (percentage: Int) -> Double {     return (Double(percentage) / 100) }  var fivePercent = 5% print( fivePercent )`

that’s all. You can use now 5% and get 0.05 as value.

Let’s see an example using PREFIX, the square root:

`prefix operator √ prefix func √(lhs: Double) -> Double {     return sqrt(lhs)  }  let someVal: Double = 25 let squareRoot = √someVal print( squareRoot )`

The last one is the INFIX operator that is used between numbers. Example:

`infix operator • func •(lhs: Double, rhs: Double) -> Double {     return lhs * lhs + rhs * rhs }  let doubleVal1 = 2.0 let doubleVal2 = 3.0  let squareSum = doubleVal1 • doubleVal2 print( "squareSum: \(squareSum)" ) //squareSum: 13.0`

this operator can be used between numbers.

Cool right?

Now, something more interesting about operators. This was the funny part, now the complicated one.

###### precedencegroup

For every operator, we can define the precedence using the keyword `precedenceGroup`.

Read more also on Apple reference: https://developer.apple.com/documentation/swift/swift_standard_library/operator_declarations

`precedencegroup PowerPrecedence {     associativity: right     higherThan: MultiplicationPrecedence }  infix operator ^^^: PowerPrecedence func ^^^ (base: Int, power: Int) -> Double {     return pow(Double(base), Double(power)) }  let fiveSquared = 5 ^^^ 2 print( fiveSquared ) //fiveSquared: 25.0`

It’s nice, but is better to do using generics, no?

You can find a recap here:

Swift – Use generics [T] with closures

`infix operator ^^ public func ^^ <T: Numeric>( value: inout T, power: Int) {     var finalValue: T = 1     for _ in 0..<power {         finalValue = finalValue * value     }     value = finalValue }`

This operator, ^^ execute the “pow” function but don’t care of the type of the value.

So you can “pow” any type you want:

`var floatValue: Float   = 28.10 var doubleValue: Double = 10.84 var intValue: Int       = 123 var binaryValue         = 0b101 var octalValue          = 0o11 var hexadecimalValue    = 0xFA  floatValue ^^ 2 print( floatValue ) //789.61005  hexadecimalValue ^^ 2 print(hexadecimalValue ) //62500`

So, valid for any type of value!

Another interesting thing is about the structures like CGRect, CGPoint, and others…

You can create an operator, for instance, to add a “delta” to the x, y, w, h of a CGRect (don’t know the utility but..) or why not to sum two different CGRect:

`infix operator ++ extension CGRect {     static func +(lhs: CGRect, rhs: CGFloat) -> CGRect {         return CGRect(x: lhs.origin.x + rhs,                       y: lhs.origin.y + rhs,                       width: lhs.size.width + rhs,                       height: lhs.size.height + rhs)     }      static func ++(lhs: CGRect, rhs: CGRect) -> CGRect {         return CGRect(x: lhs.origin.x + rhs.origin.x,                       y: lhs.origin.y + rhs.origin.y,                       width: lhs.size.width + rhs.size.width,                       height: lhs.size.height + rhs.size.height)     } }`

To avoid operator caos in your code, add it in an extension like this example.

`let frame1 = CGRect(x: 10, y: 10, width: 100, height: 100) let biggerFrame = frame1 + 10 print( "biggerFrame: \(biggerFrame)" )  let frame2 = CGRect(x: 30, y: 30, width: 300, height: 300) let frameSum = frame1 ++ frame2 print( "frameSum: \(frameSum)" )`

Result is:

`biggerFrame: (20.0, 20.0, 110.0, 110.0) frameSum: (40.0, 40.0, 400.0, 400.0)`

You can create more and more based on your needed but…

###### Should You Use Operators?

As suggested in a talk by Erica Sadun, I report some notes about using operator and why and when to use, but also when to avoid!

Main points:

• Operators lack context

Operators, especially custom ones, naturally lack the context and cues that allow you to relate information and functionality to things that you are seeing in code as you look at it.

• Association

Association helps you to narrow down concepts by relating terms to an idea. Most of all, it assists recall. In Xcode, an associated word feeds into its auto-completion system in a way that pure symbols can’t.

• Unnatural operators

Unnatural operators aren’t naturally recognizable. Put yourself into the shoes of someone reading your code and not the person who wrote the operator.

The compiler isn’t the only one who’s ever going to read your code. You are going to read your code as you write it, and you’re going to read it in a month or a year from now.

And important lessons:

Operators are precious and expensive. They involve significant mental costs for creating code for reading code, and maintaining code. Use operators sparingly.

A great operator that’s impossible to type isn’t going to get used.

Think global. First, prefer symbols that can be as easily entered on the German keyboard as a US keyboard.

When you adopt an operator use it, use it! If you’re not using an operator significantly more than you would a function, seriously consider cutting it out and just replace it with a function.

###### BONUS OPERATOR: “THE Flatter operator”

Given an array with optional values, return an array with only NOT nil values.

`postfix operator .? postfix func .?<T>(lhs: Array<T?>) -> Array<T> {     return lhs.flatMap{ \$0 } }  let numbers:[Int?] = [1, nil, 2, 3, nil, 6] print( numbers.? ) //[1, 2, 3, 6]`

My favourite!

Enjoy, but don’t forget the suggestions!