Unwrapping Optionals (Swift Playground)

329 views Asked by At

Simple question for you folks about unwrapping optionals.

I've read and seen the multiple examples of unwrapping like the following

var strArray: [String]?
strArray = ["John", "Stacy", "Stephanie" ]

if let forSureNames = strArray{
   for name in forSureNames{
      print("\(name)")
   }
} else{
    print("Failed unwrapping")
}

However, My question is for if let forSureNames = strArray{...

When typing syntax similar to C++ (and from some swift examples), adding parenthesis

if (let forSureNames = strArray){

Gives the error codes:

'()' is not convertible to 'Bool'

error: MyPlayground.playground:13:4: error: expected expression in list of expressions
if(let forSureName = strArrays){
   ^
error: MyPlayground.playground:13:4: error: expected '{' after 'if' condition
if(let forSureName = strArrays){
   ^

Can anyone help explain the difference?

Edit First time I asked a question on Stack overflow and feedback is awesome. I was trying to use a similar coding style to C++ due to my familiarity for an easy transition. However, you guys made it clear that it’s an incorrect approach. Thank you for a new and technical perspective towards unwrapping. Cheers!

4

There are 4 answers

0
Sweeper On BEST ANSWER

As you know, () can be used to surround an expression and it will have no effect on the evaluation of that expression, and you are asking "why can't I do the same to let forSureNames = strArray?" Right?

This is because let forSureNames = strArray is not an expression. You are parsing this statement wrong. The word let is part of the if let statement.

You are confusing if let statements with C-style if statements, where after the if, there is always an expression that evaluates to Bool. if let simply does not work like that. It takes the form:

if let <identifier> = <expression> { }

where expression must evaluate to an optional type. So putting () around let <identifier> = <expression> makes little sense. You could put () around strArray because that is an expression, but I don't see the point of that.

0
Robert Dresler On
if (let forSureNames = strArray) {

... this is trying to use optional binding. Optional binding allows you to safely unwrap some optional constant/variable which can be nil. If this value is assigned, it satisfies the if statement with this unwrapped (non-optional) constant/variable.

But, it doesn't work with parentheses, since values coming from parentheses have to be of type Bool. An optional binding doesn't return a Bool value directly, it just attempts to assign the constant/variable and implicitly returns a boolean based on whether the assignment occurred.

if (true) {...} // works
if (let value = optional) {...} // doesn't work

So, you have to remove these parentheses

if let forSureNames = strArray {...}

Unlike other languages, conditions in Swift don't have to be inside parentheses and it is recommended not to use them if they aren't required.

0
zneak On

Swift is vastly different from C++, so you shouldn't be surprised that C++ syntax doesn't work in Swift.

There are two type of if statements in Swift: the type that takes an expression (if foo.bar), and the type that does pattern matching (if let foo = bar, if case .some(let foo) = bar, etc).

Because Swift supports parenthesized expressions, if foo.bar works the same as if (foo.bar): in the first case, the condition is foo.bar, and in the second case, the condition is (foo.bar). In other words, the parentheses here are part of the condition expression, not part of the if statement. This contrasts with C++, where the parentheses are part of the if statement. In both cases, however, you can add as many parentheses as you want: if (((((((((foo.bar))))))))), though silly, is superficially valid in both languages.

Recall that you can wrap arbitrary expressions in parentheses, but you can't just wrap anything in parentheses. You wouldn't write (if foo.bar) in Swift or C++, because you know that if isn't an expression. Then, the same applies to let foo = bar. It's not an expression either, so you can't wrap it in parentheses. if let foo = bar is fine, but if (let foo = bar) isn't.

C++ supports a similar syntax in some cases:

if (auto foo = make_unique<int>(3)) { ... } else { ... }

This syntax declares foo and tests it (using its operator bool()), and then branches the program appropriately. Since the condition is a declaration statement, not an expression, it can't be wrapped in more parentheses either: if ((auto foo = make_unique<int>(3))) is a compile-time error, just like if (let foo = bar) in Swift.

0
rob mayoff On

Can anyone help explain the difference?

The difference is that Swift is not C++. Although they are similar in many ways, they have different grammars. The grammar defines (in part) the language's syntax.

In C++, an if statement is part of the selection-statement production in the grammar:

selection-statement:

if ( condition ) statement

if ( condition ) statement else statement

switch ( condition ) statement

So the parentheses around the condition of the if statement are part of the if statement, and not part of the condition.

In Swift, an if statement is the only production of the if-statement production in the grammar:

if-statement β†’ if condition-list code-block else-clauseopt

Note that there are no parentheses directly in the if-statement's production. So if there are to be parentheses, they must be part of the condition-list production. Here's how condition-list is defined:

condition-list β†’ condition | condition , condition-list

condition β†’ expression | availability-condition | case-condition | optional-binding-condition

So a condition-list is one or more conditions, separated by commas. If you click through each of the four alternatives in condition, you'll find that availability-condition must start with the token #availability, case-condition must start with the token case, and optional-binding-condition must start with either the token let or the token var. None of those three productions can start with a parenthesis token.

The only production of condition that can start with the token ( is the expression production, and an expression production cannot have the token let after the token (.