Sanity check:'s LanguageGuide -- result of "Int(stringName)" is sometimes an Int? but other times an Int

I'm new to Swift, just reading thru the introductory documentation. I'm surprised by some discussion in that introductory documentation, here:

From the discussion in the sections "Optionals" and then "Optional Binding", do I correctly understand that the code fragment

let convertedNumber = Int("123")

yields the inferred type Int? (an optional Int) for the constant convertedNumber,
but the code fragment

if let actualNumber = Int("123") {

yields the inferred type Int for the constant actualNumber ?

Do I have that right?
And Swift does the latter (infers Int) within "if" and "while" tests, but nowhere else?

If I'm wrong, please enlighten me.
If I've got that right, then may I suggest modifying the document to better clarify when Swift does the one vs the other? I find it surprising & quite subtle.

Thanks in advance!


Note that within the document, the code samples are actually:
Under the heading "Optionals":

1. let possibleNumber = "123"
2. let convertedNumber = Int(possibleNumber)
3. // convertedNumber is inferred to be of type "Int?", or "optional Int"

And under heading "Optional Binding":

if let actualNumber = Int(possibleNumber) {
    print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)")


I think you have it right. (Though sometimes your choice of words is slightly unexpected, so maybe there is a misunderstanding somewhere.)

It does so whenever you use it as a condition. Technically that includes a few other places, but if and while are the main ones, and they are the only ones that are beginner‐friendly. As long as you understand the nature of using it as a condition, the other places will be intuitive when you eventually encounter them.

Did you read to the end of the Optional Binding section? I really cannot think of a better explanation than it already provides.

1 Like

Int's String constructor (i.e. Int.init?(String)) is a failable constructor, and always returns Int?.

What's happening here is, as the documentation describes, optional binding. Optional binding has expressions of the form:

if let lhs = rhs { 
    // Do something with lhs

where rhs has an optional type (i.e. T?, or in this case, Int?).

The body of that block (between the {} tokens) is only executed if rhs is non-nil. If rhs is non-nil, lhs is set equal to rhs but has the type T rather than T?; since we know it's not nil, it can be used without optionality checking.

Put another way, the above code is equivalent to:

if rhs != nil { 
    let lhs = rhs! // Force unwrap rhs since we know it isn't nil.
    // Do something with lhs

Thanks. I appreciate the help.

It's a fair question: did I read to the end of the Optional Binding section. Yes... but the question had lodged in my mind prior to that. So while that further discussion did lead me to the right conclusion (as you've verified), I still retained some of my level of surprise.

The surprising thing to me is that the code let number = Int("123") does different things in different contexts. (Or change "let" to "var", for that matter.) It seems like quite a subtle difference, and once I perceived it, I was surprised that the Swift doc page didn't make more of an explicit point of it. It could add a one-liner like: "Notice that Swift infers a different type when the let statement occurs inside an if or while test, as compared to when the let occurs as an independent declaration." (or words to that effect)

But, ok. I see.

Thanks again.

PS: My unexpected choice of words may derive from me being an old C programmer. I've been out of it for years & am just now returning.

Thanks, again.

Perhaps I should modify the way I talk/think about it & say that Swift is doing an extra step, when the statement occurs inside an if or while test -- it is not only inferring a type, but also doing an extra step of unwrapping. And it's that extra step that only happens inside a logical test (if or while).

1 Like

Exactly. You’re learning to speak Swift already. :+1:

1 Like