The title is a ripoff of an old classic paper “go to statement considered harmful“. It’s a short read and a good one. The goal of my post is not to make you stop using “if let” and “guard let”. It’s more to make you feel what are you missing when you are using them.
What’s wrong with “if let”?
Nothing. It helps Objective-C developers transition from their “C” concept of nothing to a more modern Swift one. In ObjC it’s called “nil” (it has many more names check out NSHipster post about nil). Swift also has a “nil” literal which is a lie and also should not be used in my opinion 🙂
Handling nothing is a common pattern in ObjC land. You can send a message to a “nil” and you will not crash. The runtime will return you “nil”. If you want you can check if something is nil using
== operator in a
if statement. Or you can early exit from a function when something is nil. Sounds and looks like a very common pattern. Just check your codebase how many “if/guard let”s you have!
So to help with the transition from ObjC to Swift this special syntax was introduced. But Optional in Swift is something more!
Optional allows you to capture some context in a data structure. In the case of an Optional, this context is the absence of a value or value itself. Also Optional comes with two fantastic methods
map allows you to apply a function to this value and return something else. The next one flatMap does the same thing but this extra step of flattening makes sure that you are only dealing with one level of nesting of optionals when this transformation returns yet another context (Optional).
let number: String? = "42" let _: Int?? = number.map( Int.init ) let _: Int? = number.flatMap( Int.init )
Notice the types. When using
map we got a double nested optional. That because
Int.init has type
(String) -> Int?. Using
flatMap allows for removing this annoying nesting. If you dig around then you probably will find that function
map is defined on
Functor. And that function
flatMap is defined on
Monad. Sometimes you can also hear someone referring to flatMap as
I don’t want to create yet another monad tutorial so I will only say one thing. Think of map and flatMap as design patterns. The first one is how to apply value to a function. The second one is how to chain computations.
Where is the harm?
There are more types that have
flatMap operations on them but only
Optional has this special syntax. Think of Future, Promise, Result, Try, Either, Array, Vapors EventLoopFuture, and more. Today it might not be as much but tomorrow…
Tomorrow Swift might allow us to write code that does not care what type of abstraction is used (Optional, Array, Either…). If we had Higher-kinded Types one day we could write this kind of code. Treating all of them like one structure. Reusing it!
Practice is the best way to learn! Try to use
flatMap instead of
if let and
guard let. You can rename
flatMap on Optional to
andThen to see how your code can be more expressive. There is a beautiful world of composition waiting to be discovered and it’s right before your eyes!
Inspired by these functional concepts and wanted to run away from special syntax I have created a Swift Package OptionalAPI. You will find there a good readme, tests, examples on how to use it and a couple of more useful functions.