Swift: Optionally Do — Re-thinking If Let

Sometimes I wish there was a shorthand version.

I know, I know, it’s short enough. That’s what people keep telling me, but hear me out for a second.

??

We have the ?? operator in Swift, and it’s great because it’s a shorthand way of supplying a default value to an optional if it happens to be .None. For example:

What are the advantages? Well, it’s succinct (which isn’t always better but in this case I think we can call it a plus point), it’s elegant, it reduces noise, and it’s also clear to the programmer what is happening given they’re aware of the operator.

I think it’s safe to say that using ?? is strictly better than the alternative, so with that thought in mind, I began to wonder “what can we do with if let…?”

jtribe — Love Your Apps!

What’s Wrong With If Let?

Listen, I love if let and guard let as much as the next person. I think they’re great and all, but sometimes I just wish I didn’t need to write the full if let statement to unwrap and make sure the property I’m using is a non-optional.

In fact, sometimes before using a function there can be a number of optionals that I need to if let — which may bring flashbacks of the pyramid of doom to some of us — before I know it’s safe to use them. Why can’t we have a short-hand notation?

I’m not promising what i’ve got here is thorough in any way, shape or form and I can break it quite easily, so lets call this a thought experiment. Maybe you guys can think of some improvements or why it’s a good or bad idea, so please let me know your thoughts by commenting below.

Operator Abuse

Now before I go introducing you to this operator, I just have to prefix this by saying…

I really dislike the abuse of operators in programming where it compromises the readability of the code.

For example, take the JSON parsing library Argo from the guys at thoughtbot:

extension User: Decodable {

static func decode(j: JSON) -> Decoded<User> {

return curry(User.init)

<^> j <| "id"

<*> j <| "name"

<*> j <|? "email" // Use ? for parsing optional values

<*> j <| "role" // Custom types that also conform to Decodable just work

<*> j <| ["company", "name"] // Parse nested objects

<*> j <|| "friends" // parse arrays of objects

}

}

U WOT M8!? 😦

Good luck understanding anything about how that library works or what the code is doing from their “Usage tl;dr” at the bottom of the Github README. I’m sure it’s all sunshine and rainbows when you figure out what all the hieroglyphs mean but I’m not ancient Egyptian my friends, I’m not doing it.

On the other hand, take a look at the awesome SwiftyJSON:

//Getting a double from a JSON Array

let name = json[0].double //Getting a string from a JSON Dictionary

let name = json["name"].stringValue //Getting a string using a path to the element

let path = [1,"list",2,"name"]

let name = json[path].string //Just the same

let name = json[1]["list"][2]["name"].string //Alternatively

let name = json[1,"list",2,"name"].string

You can almost instantly tell exactly what it is doing with very little investment.

Alright, I got that out of my system. We’ve well and truly established that I don’t like operator abuse which compromises readability. So why on earth am I making an operator that obfuscates the if let?

Well… I don’t think it does. Much. Allow me to explain.

The Optionally Do— ?!

I came up with the idea of the Optionally Do operator — ?!

(left hand side) ?! (right hand side)

lhs ?! rhs

This operator should be read as lhs optionally do what is on the rhs, given that the lhs is a non-optional

The ? stipulates that the left-hand side (lhs) of the expression is some kind of Optional value. The succeeding ! means that the right-hand side will only execute should the lhs be successfully unwrapped.

Ok, so you might not like the operator or the name, but lets put that aside for a second. We can change that easily. Lets see what i’d love to be able to do.

I’ll highlight the examples below with comments at the top of the code block where the code will compile, and i’ll let you know when I get to theoretical land (given my current definition of the operator above).

Here’s my really basic definition:

Yeah I know, I said it was basic. Sometimes we want to call a function, even if the value we’re checking isn’t going to be used. Wouldn’t it be great that instead of having to write something like this:

We could just write this instead?

mark ?! printHello // prints HELLO

i.e. print HELLO if mark is non optional

Just like ??, it’s succinct, it’s elegant, it reduces noise and it’s also clear to the programmer what is happening given they’re (now) aware of the operator. What if we do need to use the value in the function?

// compiles func sayHi(to someone: String) {

print(“Hello \(someone)”)

} mark ?! sayHi // prints Hello mark

I think the above is cool in the sense that I don’t even need to say that I want to use mark as an argument explicitly by calling sayHi(mark) and that the compiler can infer it, but it’s not immediately obvious to the programmer so I don’t think it can be held in the same regard as the advantages of the previous example or the ?? operator. However, what we can write instead is

// compiles mark ?! { sayHi(to: $0) }

Which is better, because now I know what’s happening as the programmer. It’s a lot more readable but i’d rather we didn’t have to have the { } at all and could just write

// theoretical mark ?! sayHi(to: $0) // OR mark ?! sayHi(to: mark)

…which achieves the same purpose and is a lot cleaner than before.