14

In swift the following syntax is allowed for flow control

if let constantName = someOptional {
    statements
}

In this context what are the semantics of the truth value context ?

Is expression chaining (like below) permitted ?

if let constantName = someOptional &&  constantName2 = someOptional2 {
    statements
}

If so, does the boolean expression short circuit ?

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
  • 2
    First `someOptional` is checked to see whether or not its `nil`. If its not, then `constantName` is assigned to the unwrapped value of `someOptional`. If its `nil`, it goes to the `else` statement. This is explained to great depth in the `Intermediate Swift` vid :] – Jack Jun 09 '14 at 20:55
  • 1
    What about [the documentation](https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_432) was unclear to you? – Chuck Jun 09 '14 at 21:00
  • @Chuck It's like the first thing my eye landed on, when looking at swing. I'm **not** familiar with the notion of `nil` in this language, neither have I ever coded in it. In asking such a thing I'd also expect to derive a search method and links to the right documentation pages of the language. Didn't expect that level of elitism in such a newborn language, maybe better not to mess with a language that has such a negative community – Nikos Athanasiou Jun 09 '14 at 21:04
  • 1
    @Nikos Athanasiou: It's in the first chapter of the documentation, which is already the first result for "swift optional binding". No elitism there. The purpose of Stack Overflow just isn't to rewrite the basic documentation for a language. – Chuck Jun 09 '14 at 21:09
  • @Chuck Elitism refers to the tendency to downvote "obvious" questions. There's a ton of "obvious" questions on SO and there's always something more to learn by asking people that use these stuff. – Nikos Athanasiou Jun 09 '14 at 21:14
  • 1
    @NikosAthanasiou: From the tooltip on the downvote button: "This question does not show any research effort." That is what the button is there for. I don't think expecting somebody to at least glance at the basic documentation or check the first result on Google before asking a question is elitist, because there is nothing elite about that. I'm sorry that downvotes are unpleasant, but this really is a completely unresearched question and it isn't useful to anyone who has read one single chapter of the Swift introduction. – Chuck Jun 09 '14 at 21:19
  • @Chuck [This](http://stackoverflow.com/q/1292189/2567683) is how a healthy code community reacts on such questions. FWIW that was also the place where I learned the Python `for` loop. 8.5K views and a ton of useful info. If you're the self appointed sherif of this tag be careful on how you treat it and which code society you want to be like, because the users and community mark the success or failure of a language. – Nikos Athanasiou Jun 09 '14 at 21:46
  • 1
    @NikosAthanasiou: I feel like you're making this more hostile than it needs to be. I'm just a guy who likes Stack Overflow and upvotes good questions and downvotes not-so-great questions. I'm not out to get anyone, and I try to comment on what's lacking so people can hopefully improve their answers. That Python question you linked is from 2009. There are a lot of questions from back then that actually aren't up to the site's standards and wouldn't be as well-received nowadays. SO was very different back then because it was much smaller. I miss it too, but we can't turn back the clock. – Chuck Jun 09 '14 at 22:13
  • @NikosAthanasiou I think you should mark my answer as the correct solution. – Van Du Tran Jan 13 '16 at 16:39
  • @VanDuTran Provide more info, elaborate on the rationale and explain your code and I'll consider altering my choice. As is, your answer, got my upvote but it's too dry for a tick (also if `,` works a sequence point as in C++ I don't think we mean the same thing by chaining ie expressions not only evaluated but short circuiting as well .. can't know, cause you just present code) – Nikos Athanasiou Jan 13 '16 at 17:05

9 Answers9

23

First someOptional is checked to see if it's nil or has data. If it's nil, the if-statement just doesn't get executed. If there's data, the data gets unwrapped and assigned to constantName for the scope of the if-statement. Then the code inside the braces is executed.

if let constantName = someOptional {
    statements
}

There's no way to chain this functionality in one if-statement. let constantName = someOptional does not directly evaluate to a boolean. It's best to think of "if let" as a special keyword.

Dash
  • 17,188
  • 6
  • 48
  • 49
  • Sorry for altering the question, it took much too bullying to let alone, please see the edit and if willing provide some extra info. – Nikos Athanasiou Jun 09 '14 at 21:35
18

In Swift 1.2 and 2.1, you can do this:

if let constantName = someOptional, constantName2 = someOptional2 {
    // statements
}
Van Du Tran
  • 6,736
  • 11
  • 45
  • 55
8

You can't chain the optional binding like this:

if let constantName = someOptional && constantName = someOptional2 {}

but in Swift 1.2 you can write this:

if let constantName = someOptional, constantName = someOptional2 {}

What's going on here?

Optionals are their own type and are Swift's way of providing compile time checking for nil. When you type var potentialValue : Int? you are not using some special Int, you are using the Optional type, which is essentially an empty enum. This is why you often have to unwrap the optional with the ! as this allows you to access what's inside (if there is anything inside). If the optional contains no value (i.e. the enum is empty) then it has a value of None. If the optional is not empty then it has a value of Some and an associated value of whatever type you are using - so in this case an Int.

This:

if (someOptional != nil){
    let constantName = someOptional!
}

is the same as using this:

if let constantName = someOptional {}

which is called optional binding. You'll notice that the second version here is a little more readable and you don't have to explicitly unwrap the optional using the !.

It evaluates to true when the optional's value is Some and not None - in other words, when the optional is not nil. (Notice that you can still check for nil if you like and you can also change an optional's value back to None by writing someOptional = nil.

Something else that hasn't been mentioned is that you can use ?? (called the nil coalescing operator) to give an optional a default value if it doesn't have one. For example:

let constantName = someOptional ?? 100

Here someOptional will be unwrapped if it has a value but if it doesn't then the value 100 is used instead.

I find it useful to remember that optionals are their own type in Swift. They aren't a fancy version of the type that you are saying they contain.

Gordonium
  • 3,389
  • 23
  • 39
  • Note to readers: The `==` in the first two examples of `if let` should be a single `=`. – Noein Sep 26 '15 at 18:25
  • 2
    ```You'll notice that the second version here is a little more readable```. I'm sorry to disagree. First version is much more readable, but second version is more concise. Concise is not always more readable – mradzinski Aug 18 '16 at 18:42
3

First someOptional is checked to see whether or not its nil. If its not, then constantName is assigned to the unwrapped value of someOptional. If its nil, it goes to the else statement.

This means, that even if someOptional is a Bool? which is assigned to false, it will still go into the first block, not the else.

The Intermediate Swift video goes into much depth on this topic, in the first 15 minutes!

Jack
  • 16,677
  • 8
  • 47
  • 51
  • Sorry for altering the question, it took much too bullying to let alone, please see the edit and if willing provide some extra info. – Nikos Athanasiou Jun 09 '14 at 21:35
2

Think of it like this: An optional is just an Enum with an associated value.

enum OptionalValue<T> {
    case None
    case Some(T)
}

When you assign to an optional, under the hood the .Some enum value is used, with an associated value that you gave. If you assign it to nil, it's given the value None, with no associated value.

if let constantName = someOptional {}

Does the if on the enum. If it's .Some, then the constant is assigned the associated value, and the block is executed. Otherwise nothing happens.

Steve Waddicor
  • 2,197
  • 15
  • 20
  • Sorry for altering the question, it took much too bullying to let alone, please see the edit and if willing provide some extra info. – Nikos Athanasiou Jun 09 '14 at 21:36
1
if let constantName = someOptional {
    statements
}

Basically what is happening here is that if someOptional has a non-nil value, constantName is assigned someOptional value for the scope of this if-statement.

In terms of semantics, the order of how things happen is A) someOptional is checked for nil, B) and then it is assigned to constantName, and then finally, C) statements in the if-block are executed.

Usually, the value of doing something like this is that it prevents the app from crashing if you otherwise have a nil-value. It is worth noting that the nil in Swift if different from Objective-C because it is more powerful than simply a pointer.

Also, if someOptional is a Bool that is False, do note that it will still execute that if-block because it is not checking for true/false but rather the presence/absence of value. The presence of False renders the if-block true.

haxgad
  • 387
  • 4
  • 9
1

From the Apple Doc

Optional Binding

To conditionally bind the wrapped value of an Optional instance to a new variable, use one of the optional binding control structures, including if let, guard let, and switch.

if let starPath = imagePaths["star"] {
    print("The star image is at '\(starPath)'")
} else {
    print("Couldn't find the star image")
}

Optional Chaining

To safely access the properties and methods of a wrapped instance, use the postfix optional chaining operator (postfix ?). The following example uses optional chaining to access the hasSuffix(_:) method on a String? instance.

        if let isPNG =imagePaths["star"]?.hasSuffix(".png") {
            print("The star image is in PNG format")
        }
        // Prints "The star image is in PNG format"
Balagurubaran
  • 549
  • 6
  • 18
0

The optional binding

Swift 2

   if let constantName = someOptional, constantName2 = someOptional2 {
                // your statement goes here .....
                print(constantName)
                print(constantName2)
            }

swift 3

if let constantName = someOptional, let constantName2 = someOptional2 {
            // your statement goes here .....
            print(constantName)
            print(constantName2)
        }
0

Optional chaining example :

let object : Int ? = 3

if (object =! nil) { print (object! as Any)

}

if let objOptChaining = object { print(objectChaining)

}

Optional Binding Example :

let object : Int ? = 3

if let objOptBinding = object{

// objOptBinding hold the value

} else {

// no value }
GordonShumway
  • 1,980
  • 13
  • 19
Anshu
  • 1
  • 1