Swift: The Unused Optional Value Problem

Yesterday, I had an interesting discussion involving Swift optionals with my co-workers. Here is a scenario – you need to do something in your code based on whether an optional value exists or not, but the thing you need to do does not need to actually use the optional value.

So here is the first try for this simple logic:

var someOptionalVar: String?

someOptionalVar = "something there"

if someOptionalVar != nil {
    // execute code that does NOT actually
    // use someOptionalVar
    println("hello")
}

This immediately stood out as “wrong” to me. By now, I’m very well trained to unwrap optionals all the time, so having a != nil just feels wrong in Swift. Also, I don’t like the != here – I had to do a double take to realize that this code executes if something is actually there, so to me, it’s also not as readable. Of course, this code works and is completely “correct” for the situation, if that’s what you prefer.

My immediate response was to use the unwrapping syntax in Swift instead:

var someOptionalVar: String?

someOptionalVar = "something there"

if let someVar = someOptionalVar {
    // execute code that does NOT actually
    // use someVar
    println("hello")
}

The problem here, as my coworkers pointed out, is that it’s creating a variable that’s not going to be used. And it’s equally, if not more confusing than the above solution, because reading this code, one immediately starts looking for the use of the unwrapped value, and it’s confusing that it’s not actually used (did the person forget to use it? should I use it?).

Luckily, @jsambuo pointed me to the perfect solution (IMHO) from this StackOverflow post, that I didn’t think of, but makes perfect sense.

var someOptionalVar: String?

someOptionalVar = "something there"

if let _ = someOptionalVar {
    // execute code that does NOT actually
    // use someOptionalVar
    println("hello")
}

This way, you still get to use the traditional Swift unwrapping optionals syntax, but it’s now very clear that you do not intend to use the unwrapped value.

Good reminder to use the _ in Swift for a lot more readable code, something that I often forget.

UPDATE: I now realize that this post reads as me saying that I “know” the right answer, and the right answer is the let _ = someOptionalVar option. The truth is, when my coworkers discussed this, we didn’t come up with the “right” solution, just preferences.

All I know is that when I saw the != nil in the Swift code, it took me a minute to process it and understand it, since it just wasn’t in the same Swift format that I’m now so used to for optionals. In any other language, I wouldn’t have given it a second thought.

And, rightly so, I’ve received comments that the != nil solution is way better and readable: see discussion on Twitter here, here, here, here, and here. In fact, Apple uses the != nil version in their own walk-through on Optionals.

The best way I can describe why the if let _ excited me so much is these tweets from @dandon and @jrbj:

Just like @dandon and @jrbj, I’ll have to try it out and see how I like it, and how my team feels about it in the actual codebase. Meanwhile, I’m keeping an open mind as I keep learning and discovering Swift. So I hope you read this and my other posts as a Swift exploration rather than a prescription.

Enjoy the article? Join over 17,500+ Swift developers and enthusiasts who get my weekly updates.

  • Mr_Beardsley

    In my opinion I think using the unwrapping syntax for a test is more convoluted than just testing for nil. Of course if you don’t like nil you can also use:

    var optionalVar: Int? = 0

    if optionalVar != Optional.None {
    println(“optionalVar has a value”)
    }

  • Jessy Catterwaul

    C# 2.0 gave us a better solution: http://stackoverflow.com/questions/676078/which-is-preferred-nullable-hasvalue-or-nullable-null

    extension Optional {var hasValue: Bool {return self != nil}}

    Swift doesn’t have that, because the .HasValue / .Value pattern, where .HasValue is used the most, is improved by the if let syntax.

    • I disagree that if let _ is an improvement over .HasValue. The if let syntax is really nice where you’re using a required value, but I feel like if let _ just adds cognitive overhead.

      • Jessy Catterwaul

        I didn’t agree that _ was an improvement over anything; I said that the “if let” pattern is an improvement over the .HasValue + .Value pattern. .Value isn’t relevant to this post, though. I like .hasValue better, for now, just because the ! operator is useless. ~ is more universal and would cause no issues, with Swift’s types, like it would in C.

    • Vjosullivan

      It seems to me that this is by far the best solution (sorry Christopher). The code states explicitly what is going on. It’s self documenting which is always good.

  • Using “if let _” solely for a nil check obfuscates the intention and makes it harder to understand when another developer needs to read the code a week/month/year from now. I’m all for using advanced language features if it makes the code more readable or concise but this achieves neither goal so my vote is to stick with good old “if someOptionalVar != nil”

  • Farmertjes

    Why not

    var someOptionalVar: String?

    someOptionalVar = “something there”

    if let someOptionalVar = someOptionalVar {

    }

    • They just have the same name, but they are not the same variable at all. You could mark someOptionalVar as “let”, and it will still work.

  • Rich G

    What about doing this kind of thing? Am I terrible for wanting to do things this way?

    if myOptional == nil{
    //handle case where optional is nil.
    return;
    }

    let aValue = aValue()
    aValue.stuff = myOptional!

    At least this way I have one fewer level of nesting…

    • Rich G

      I suppose this won’t work for all situations….

  • vanylapep

    IMHO, I like the if let _ = as the != makes me nervous because i’m not used to it (in Swift). However, what is the impact “memory” wise since the if let _ = does create an unused variable?

  • Pingback: Michael Tsai - Blog - Swift: the Unused Optional Value Problem()

  • johnlabarge

    Depending on the situation you could just make a function that reads nicer. E.g. If (optionalMode())

  • Drew Cover

    (I wish it didn’t say I could log in with twitter but then force me to sign up with disqus. However, I like your site, Natasha, and I am interested in this discussion, so here I am.)

    It is absolutely true that ‘!= nil’ is the long standing idiom for this. However it isn’t a very good one, being a double negative. The Swift way to test for existence is ‘if let’. ‘if let _’ is great because it cues the reader that you don’t need the unwrapped variable. I think it will become a standard Swift idiom that all Swift programmers will be comfortable with. No one, now, can read Swift without understanding ‘if let’, so it won’t be an issue. IMO.

    I am more undecided about
    if let car = car { car.start() }
    instead of
    if let realCar = car { realCar.start() }’
    or
    if car != nil { car!.start() }

    What do you think?

  • Excellent article, this really made me think differently about optionals in Swift. Thank you.

  • Jim Tucker

    Your solution now generates an unused value warning in Xcode 7. Tie breaker…

  • How about using a switch statement?

    switch(someOptionalVar) {
    case .Some:
    print(“hello”)
    case .None:
    break
    }

  • I wish we could just do if optionalVar { ... like before, that was the most readable option 🙁 I don’t like any of the two currently available ones…

  • well cool solution :),
    I usually prefer to use guard and guard the code, for the cases that could break the thing on top and on the bottom in function body I have the unwrapped optional

    var a:Int?

    guard let _ = a else {
    print(“test”)
    return
    }

    guard let unrwappedA = a else {
    print(“test”)
    return
    }

    //here below I have the unrwappedA

    • Drew Cover

      It is true that guard has sadly polluted the idiom since guard let car = car is not legal and I don’t see a way to make it legal without adding a new thing for programmers to learn. Still, guard is worth it: (As Natasha said, making “happy path” clear and reducing pyramids.)

  • Curious to throw my hat in the ring, why not the following?

    var someOptionalVar: String?

    var isOptionalVarEnabled:Bool {
    return someOptionalVar ! = nil
    }

    if isOptionalVarEnabled {
    // execute code that does NOT actually
    // use someOptionalVar
    println(“hello”)
    }