Let's fix `if let` syntax

Here are some ways to make a variable nil after checking if it's not nil

var _returnedAlready = false
/// returns `.some` once, and then always `.none`
func returnOnce() -> Int? {
    if _returnedAlready {
        return nil
    } else {
        _returnedAlready = true
        return 123
    }
}

class C {
    var variable: Int? = 123
}
let c = C()
var global: Int? = 123
func unrelatedFunction() {
    c.variable = nil
    global = nil
}

/// This function takes `Int`. What happens if you pass the original variable which is now nil?
func takesInt(_ arg: Int) { }


func computedVariable() {
    var variable: Int? { returnOnce() }
    if unwrap variable { // We get into the scope, because `variable` is `123`
        takesInt(variable) // oops! variable is `nil` here
    }
}

func structProperty() {
    struct S { 
        var variable: Int? = 123
        mutating func f() {
            variable = nil
        }
    }

    var s = S()
    if unwrap s.variable {
        s.f()
        takesInt(variable) // oops!
    }
}


func classProperty(c: C) {
    if unwrap c.variable {
        unrelatedFunction()
        takesInt(variable) // oops!
    }
}

func global() {
    if unwrap global {
        unrelatedFunction()
        takesInt(global) // oops!
    }
}

func propertyWrapper() {
    @propertyWrapper
    struct Wrapper {
        var wrappedValue: Int? { returnOnce() }
    }

    @Wraper var variable: Int?

    if unwrap variable {
        takesInt(variable) // oops!
    }
}

Even if it were true, we still have the current if let for those things when needed, right?

This thread is about making something better than if let. It would be a shame if the result is that I still need to use if let 90% of the time. :(

3 Likes