public static void
public static void

Reputation: 1193

Why are multiple unwrapping optionals impossible?

I've been playing with optionals in swift. I make frequent use of the conditional unwrap pattern:

var myOptional: AnyObject?
if let unwrapped = myOptional {
// do stuff
}

However, on occasion I have two optional values that I only want to use if both of them are non-nil. As such, I tried to use the following syntax:

var myOptional: AnyObject?
var myOtherOptional: AnyObject?
if let unwrapped = myOptional && let otherUnwrapped = myOtherOptional? {
// do stuff
}

I've tried putting the two parts in brackets etc. but there doesn't seem to be a way to do this. Is there a good reason why I shouldn't be able to do it? Obviously I can just embed one statement in the other but I would prefer to put it all on one line.

Upvotes: 1

Views: 230

Answers (4)

Marius Fanu
Marius Fanu

Reputation: 6669

Starting with Swift 1.2 you can unwrap multiple optionals and conditions.

The “if let” construct has been expanded to allow testing multiple optionals and guarding conditions in a single if (or while) statement using syntax similar to generic constraints: if let a = foo(), b = bar() where a < b, let c = baz() { } This allows you to test multiple optionals and include intervening boolean conditions, without introducing undesirable nesting (i.e., to avoid the “pyramid of doom”).

Upvotes: 6

Ramzi Khahil
Ramzi Khahil

Reputation: 5052

The only way is to nest if statements. I think this is because apple implemented it as syntactic sugar. So the pre compiler converts

var myOptional: AnyObject?
if let unwrapped = myOptional {
    // do stuff
}

into

var myOptional: AnyObject?
if myOptional != nil {
    let unwrapped = myOptional
    // do stuff
}

You can of course do this by yourself in a single if, but this will make your code only a little prettier. On the downside, you won't know which one caused the crash while debugging.

For more information see the documentation

Upvotes: 0

LukeTerzich
LukeTerzich

Reputation: 554

    var myOptional: AnyObject?
    var myOtherOptional: AnyObject?
    let unwrapped: AnyObject? = myOptional,  otherUnwrapped: AnyObject? = myOtherOptional?
    if (unwrapped != nil && otherUnwrapped != nil) {
       // Do Stuff 
    }

This is another way you could do it. Swift is looking better day by day

Upvotes: -1

rintaro
rintaro

Reputation: 51911

Because the language doesn't support it.

In the document:

The value of any condition in an if statement must have a type that conforms to the BooleanType protocol. The condition can also be an optional binding declaration, as discussed in Optional Binding.

The condition must be an "expression of BooleanType" or an "optional binding declaration". And "optional binding declaration" is not an "expression" so you can't join with &&.

Instead, you can do that with switch:

switch (myOptional, myOtherOptional) {
case let (.Some(unwrapped), .Some(otherUnwrapped)):
    // do stuff
    println("\(unwrapped), \(otherUnwrapped)")
default:
    break
}

Upvotes: 5

Related Questions