66

In the "The Swift Programming Language" book (page 599), I came across this code snippet that kind of confused me. It went like this:

func buyFavoriteSnack(person:String) throws {
    let snackName = favoriteSnacks[person] ?? "Candy Bar"
    try vend(itemName:snackName)
}

Its explanation was:

The buyFavoriteSnack(_:) function looks up the given person's favorite snack and tries to buy it for them. If they don't have a favorite snack listed, it tries to buy a candy bar. If they...

How can this explanation map to the "??" operator in the code given. When should/can we use this syntax in our own code?

avismara
  • 5,141
  • 2
  • 32
  • 56

5 Answers5

92

It is "nil coalescing operator" (also called "default operator"). a ?? b is value of a (i.e. a!), unless a is nil, in which case it yields b. I.e. if favouriteSnacks[person] is missing, return assign "Candy Bar" in its stead.

Vega
  • 27,856
  • 27
  • 95
  • 103
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • 1
    Yup, Google wasn't helpful with the question marks. Somehow I missed this in my studies. The nil coalescing operator did it for me. – avismara Jun 11 '15 at 05:18
  • If the value of `a` is non-nil, the value of `b` is not evaluated. This is known as short-circuit evaluation. – iDhaval Jun 11 '15 at 05:58
  • The big problem with the ?? operator in Swift is that `a` is not unwrapped as a part of it. But `b` has to be a none optional or implicit unwrapped optional variable. – Morten Holmgaard Jan 07 '16 at 07:31
  • 1
    @MortenHolmgaard: What do you mean? ["The *nil coalescing operator* (`a ?? b`) unwraps an optional `a` if it contains a value, or returns a default value `b` if `a` is `nil`"](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID72). – Amadan Jan 07 '16 at 07:47
  • @Amadan Strange - your right it seems, I just testede it in Playground, but I have multiple places in my apps where I have had to handle this case manually not to get optional(somevalue) when formatting a string. – Morten Holmgaard Jan 08 '16 at 07:23
29
let something = a ?? b

means

let something = a != nil ? a! : b
Bader Al-Rasheed
  • 458
  • 1
  • 7
  • 13
26

This:

let snackName = favoriteSnacks[person] ?? "Candy Bar"

Is equals this:

if favoriteSnacks[person] != nil {
    let snackName = favoriteSnacks[person]    
} else {
    let snackName = "Candy Bar"
}

Explaining in words, if the let statement fail to grab person from favoriteSnacks it will assigned Candy Bar to the snackName

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
Icaro
  • 14,585
  • 6
  • 60
  • 75
5

The nil-coalescing operator a ?? b is a shortcut for a != nil ? a! : b

Floern
  • 33,559
  • 24
  • 104
  • 119
Muhammad Naeem Paracha
  • 2,335
  • 2
  • 18
  • 23
0

One addition to @Icaro's answer you can declare values without initialize them. In my opinion this is better:

func buyFavoriteSnack(person:String) throws {
    // let snackName = favoriteSnacks[person] ?? "Candy Bar"
    let snackName: String

    if let favoriteSnackName = favoriteSnacks[person] {
        snackName = favoriteSnackName
    } else {
        snackName = "Candy Bar"
    }

    try vend(itemName:snackName)
}
mustafa
  • 15,254
  • 10
  • 48
  • 57