comment 0

#29 An alternative to if let and guard let

It’s brilliant when you can work with people smarter (or even a lot smarter) than you! You can learn so much from them. And then write about the things you’ve learned 🙃.

if and guard let

Have you ever been tired of repeating if let or guard let statements, to perform certain operations, that should be performed only if a value is not nil? From time to time your code could become like this if you wanted to call a function with unwrapped value:

or like this:

Sometimes, it’s too much typing, isn’t it? But there’s an alternative …

flatMapping from T→Void

Optionals are monads, on which you can call flatMap function, that unwraps an optional (of hypothetical type A, a.k.a Optional<A>) if it contains a value, applies to it a transform, that converts a value from type A to type B and wraps it back into an optional of type B (a.k.a. Optional<B>). PS. if you want to understand functors, applicatives and monads I strongly recommend this video.

So, if we have an optional, we can call flatMap on it. We have to pass a closure transforming from A→B to the function. What if we wanted to transform from T→Void?

It would work. According to Swift compiler, transformation from T to nothing (a.k.a. Void) is a valid transformation. So let’s use that fact!

Note that we don’t have to use a capture list (see more on them here) since flatMap takes a non-escaping closure as an argument. In my opinion the real beauty of the solution meets the eye here:

Neat! We can append error to the array, only if it contains a value. We got rid of guard let similarly to if let in the previous example.

Drawbacks

Seeing code with transforms from T→Void in flatMap might seem a bit odd at first glance. It was odd for me. But once I’ve seen it used multiple times in the code that would require a few if lets in a row I started appreciating the solution. Check it out, maybe you will start using it too! 🙂

Final words

Big thanks to people I work with for the things I’ve been learning from you ❤️!

References

Update 4.12.2016 21:30

We’ve received a tip and correction from Ole Begemann. Thank you Ole ❤️🙃!

There’s a mistake in flatMapping from T→Void paragraph. It actually describes map instead of flatMap function. The map function takes a transform closure from T→U, whereas flatMap from T→U?. You can see declarations below:

So actually map and flatMap would have the same effect in our scenario. You can check this snippet in a Playground to see how it works!

Update 5.12.2016 9:30

@rosskimes had a good thought – forEach in the example can actually be replaced by let errors: [Error] = bars.flatMap { $0.error }. So, let us show you a more convincing example.

In snippet below CoreDataWorker mentioned in issue #28 is used to remove all entities from the database. A dispatchGroup synchronizes delete operations. All potential errors are appended to an array and processed when all operations are finished.

Leave a Reply


*