Learn Swift From the Standard Library: A Deep Dive Example
Tags: swift, ios, codequality
Published: 2020-06-20 11:03:15

Swift is a very powerful language. It has a lot of nice built-in capabilities to improve both performances and efficiency that one get to discover along the way while becoming more familiar with the language.

And a few days ago, I found out that one of the best way to discover new features is to explore an amazing showcase of Swift language characteristics, which is... The Swift Standard Library itself!

To convince you, I'll show you in this article how the `&&` operator from the `Bool` class is implemented, and how it helps us understand really well two very nice concepts, namely:

- The `rethrows` declaration (I wish I had discovered this before)
- The `@autoclosure` attribute 

I learnt about this example in [this awesome talk](https://www.youtube.com/watch?v=wB-bi8_rSLs) from Paul Hudson, which I recommend you to watch. 

I thought I could explain this from another angle, by trying to reimplement the operator from scratch by ourselves - so that we discover on the road how we come to actually need those interesting concepts.  

So, let's reimplement the `&&` operator of the Swift Core library!

If you come from the JavaScript world (or some other languages), be careful, `&&` works only with actual `Bool` types (`true && "Hello"` won't compile). Keep that in mind if you plan to give it a try by yourself. 

How would you implement such an operator ? Try to think about it, it will help you understand later why we would need such things like `rethrow`.

To try it at home, open a playground in Xcode (File > New > Playground). In 30 seconds max, you have a sandbox ready to make your experiments.

To make tests without conflicting with the existing operator, let's define a new operator, and name it for instance `&&&`:

```swift
precedencegroup CustomAnd {
}
infix operator &&&: CustomAnd

extension Bool {
    public static func &&& () -> {}
}
```

Now let's try to implement it. This is my first shot:

```swift
public static func &&& (lhs: Bool, rhs: Bool) -> Bool {
   return lhs ? rhs : false
}
```

This looks good, right ? We take two parameters, and we return true only if the left hand side `lhs` is true as well a the right hand side `rhs`.

Let's see if this works along with a small function:

```swift
func canVote(withAge age: Int) -> Bool {
    print("verifying that user is allowed to vote...")
    return age >= 18
}

print(true &&& canVote(withAge: 30))
```

It works, right ? We see following logs, and that's what we expected:
```
> verifying that user is allowed to vote...
> true
```

Let's try this example now:

```swift
print(false &&& canVote(withAge: 30))
```

```
> verifying that user is allowed to vote...
> false
```

Oh, Crap! This is not what we expected. I mean OK, the final result is correct, but I didn't expect the first line here. In Swift, the `&&` operator is lazy, we don't want the right hand side to be evaluated if the left one is false! 

To handle this, what about considering the right hand side as a closure, that would be executed only when we need to ? Sounds like a good idea, let's do this:

```swift
public static func &&& (lhs: Bool, rhs:  () -> Bool) -> Bool {
   return lhs ? rhs() : false
}
```

`rhs` is now a function, so we need to pass it a closure. Have a look at [the doc about closures](https://docs.swift.org/swift-book/LanguageGuide/Closures.html):

> Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.  

So now, we could use our operator like this:

```swift
print(false &&& { canVote(withAge: 30) })
```

Wow bro, it solves the problem, but that's not cool at all.

Yeah, sorry. We want the right hand side to keep looking as a an actual boolean, it's ugly having to explicitely pass a closure. 

Swift saves us here with the `@autoclosure` attribute for our parameter to handle that:

```swift
public static func &&& (lhs: Bool, rhs: @autoclosure () -> Bool) -> Bool {
    return lhs ? rhs() : false
}
```

The function signature is the same, it expects a function as a right hand side parameter. But this time, you can do it implicitely: Swift will create the closure returning the expression for us.

So cool, it really solves the issue ! Now, if the left side is false, the right side won't be evaluated, and I can still use my operator easily without knowing that I'm using a closure here. 

I have a warning though: :warning: Don't overuse autoclosures in the everyday life. It's a syntaxic conveniance to omit braces when it makes sense, you should probably keep them in most cases to make it clear that it may not be executed. 

This kind Note in Swift doc state it well:
> Overusing autoclosures can make your code hard to understand. The context and function name should make it clear that evaluation is being deferred.

So we found a solution, but did you notice the new problem it raises? What if we use an expression that can throw ? Before using an autoclosure, it was not a problem since the left-hand side and the right-hand side where evaluated before being passed to our function, so we could use a try statement as usual.

For instance, let's consider this function which can throw if we feed it with an integer lower than 0:

```swift
func canVote(withAge age: Int) throws -> Bool {
    guard age > 0 else {
        throw CustomError.NegativeAgeError
    }
    return age >= 18
}
```

Before using `@autoclosure`, following code could compile:

```swift
print(try true &&& canVote(withAge: 30))
```

But now, Swift compiler gets angry because we specified that the second parameter is a closure **that do not throws**, as clearly explained by the error:

```
> Call can throw, but it is executed in a non-throwing autoclosure
```

Well, I have to admit that the compiler is definitely right.

If we want to be able to use our custom `&&&` parameter with an expression that can throw (and we will!), we need to add the declaration to the rhs autoclosure and use a try before calling it. So let's rewrite it:

```swift
extension Bool {
    public static func &&& (lhs: Bool, rhs: @autoclosure () throws -> Bool) -> Bool {
    return lhs ? try rhs() : false
    }
}
```

Arf. It's still not compiling: 

```
> Errors thrown from here are not handled
```

Well, that makes sense. Our operator should either handle errors or throw now. Let's go with the second solution, and add the declaration:

```swift
extension Bool {
    public static func &&& (lhs: Bool, rhs: @autoclosure () throws -> Bool) throws -> Bool {
    return lhs ? try rhs() : false
    }
}
```

Yay, it works. Now I can use a throwing expression on the right hand side as well.

But do yo see the new problem here ? 

Yes that's right ! Now, our operator is a throwing function, so I **have to** use a `try` statement. Now we can't even compile a simple `false && true`! (We would get **Operator can throw but expression is not marked with 'try'**)

And that's where, if you are not already, should become a Swift enthusiast. 

We can use the `rethrows` declaration: It means that our method throws only if it's used with a closure which throws. All that simple. 

If we come back to our problem, we now write:

```swift
extension Bool {
    public static func &&& (lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool {
    return lhs ? try rhs() : false
    }
}
```

And now we can write `true && false` without any issues, because the closure generated for the right hand side doesn't throw, so thanks to `rethrows`, our operator is **not** a throwing function, and thus, no need to use `try`.

On another hand, if we use a throwing expression, then we need to add a try. From the developer point of view, the behaviour is exactly the same as if we were passing two boolean, as our first naive implementation.

This is the actual implementation of the && operator in the Swift Standard Library. You can double check it in [swift source code](https://github.com/apple/swift/blob/master/stdlib/public/core/Bool.swift).

I'm really amazed by the number of concepts such a basic feature contains:
- A `rethrows` declaration, [read the Swift doc](https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID531)
- A `throws` declaration
- An `autoclosure`, [read the Swift doc](https://docs.swift.org/swift-book/LanguageGuide/Closures.html#ID543)
- A ternary condition

If you're interested to go deeper, [this video](https://www.youtube.com/watch?v=wB-bi8_rSLs) from Paul Hudson showcase the swift standard library with this particular example, as well as others even more interesting, focused on improving security and performance. 

The entire Swift core library is full of interesting patterns and optimisations. It's definitely worth to have look inside it, if you want to randomly discover new interesting concepts, or find an example of something you already know, but don't understand well.