Hacker News new | past | comments | ask | show | jobs | submit login

From your comment looks like you do not get Swift anf that prevents from getting why it is loved. There is no need to "fiddle" with ? and ! Optionals are not that complex. And there is nothing wrong with let. It has nothing to do with optionals.



"if let x = someOptional" unwraps the optional, no?

And "let x = someOptional" doesn't, right?

So the first form does have something to do with Optionals, and it is true that the two forms of let behave differently with respect to them.

(I have moved on from Swift, so if things have changed since Swift 3.x and 4.something, my apologies.)


I agree that's confusing coming from an imperative context. The core misunderstanding here is that `let` is a binding, not a variable declaration. It's binding a name to a value, not creating a variable which can be modified. Therefore the `if let` example is saying "if we can bind the value inside the optional to a name", while the regular let example is just saying "bind the optional to x"


I get all that, but in one case the type of the value bound to the declared identifier is T, and in the other case it is T?. To me, that violates The Law of Least Astonishment, but that is admittedly subjective.


Actually, in `if let x = someOptional`, you should rather see it like this: `if (let x = someOptional)`. If that second part were a function, it would be `() -> Optional<T>`.

That is to say, the if statement is satisfied if the "result" of the "function" (if you follow me; clearly I don't mean it's actually a function in the implementation) returns .some(T) (not nil) rather than .none (nil).

That we can do an assignment with `let` is just syntactic sugar for:

    if someValue != nil {
        let x = someValue!
    }
Basically, we want to know if the value is non-nil. There are instances where the result can be nil, and if so, nothing gets assigned. For example:

    protocol Fruit { }
    protocol SeededFruit: Fruit { }
    protocol SeedlessFruit: Fruit { }
    struct Mandarin: SeedlessFruit { }

    let mandarin = Mandarin()
    
    if let someFruit = mandarin as? SeededFruit { }
Okay, so the compiler will actually disallow this, but you get the basic idea: `mandarin` is not a SeededFruit, the cast will always be false, therefore someFruit will be nil, therefore the "result" of the "function" will be nil, which is counted as false.

The thing is, this isn't specific to the `let` keyword, either. You could just as easily define a new variable with the `var` command.

So `let` and `var` don't mean different things in different contexts and never have. Swift just allows them to be used as syntactic sugar in if statements.


Just a late addition to anybody who sees this, I tend to think of `if let` and `if var` statements in Swift as syntactic sugar for:

    switch someOptional {
        case .none:
            // whatever
        case .some(let x):
            // do stuff with x
    }




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: