3

My Playground code:

let nickName: String? = nil
let fullName: String = "John Appleseed"

let informalGreeting = "Hi \(nickName ?? fullName)"

Hi John

let informalGreeting2 = "Hi \(fullName ?? nickName)"

Hi Optional("John Appleseed")


I thought I understand the first case

let informalGreeting = "Hi \(nickName ?? fullName)"

nickName is nil, so the output has to be "Hi \(fullName)" => "Hi John Appleseed"

in the second case

let informalGreeting2 = "Hi \(fullName ?? nickName)"

the first value fullName is not nil , so the output should be "Hi \(fullName)" => "Hi John Appleseed" in my opinion.

BUT WHY is the output an optional wrapped output like here

Hi Optional("John Appleseed")

2 Answers 2

6

There are two ?? operators:

public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T

public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?

If we simplify the declarations by ignoring that the second parameter is a possibly throwing autoclosure, we get

public func ??<T>(optional: T?, defaultValue: T) -> T    // (1)

public func ??<T>(optional: T?, defaultValue: T?) -> T?  // (2)

In nickName ?? fullName, the first argument is an optional and the second a non-optional, which means that the first variant is used, and the result is a non-optional:

nickName ?? fullName   // (String? ?? String) -> String

If nickName != nil then the result is the unwrapped (!) nickName, otherwise fullName.

In fullName ?? nickName, the first argument is a non-optional and the second one an optional. This does not match any those function declarations.

What the compiler does is to "wrap" the first argument into an optional in order to make it compile (using the second variant). The result is an optional:

fullName ?? nickName   // (String? ?? String?) -> String?

The result will always be Optional(fullName).

In a compiled project you will also get the warning

warning: left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used

The second variant is usually used when chaining nil-coalescing operators:

let result = optA ?? optB ?? optC ?? nonOptD
                  (2)     (2)     (1)
Sign up to request clarification or add additional context in comments.

Comments

1

The problem is that nickname is optional, so in the second case you are telling that if fullname is nil print nickname, but nickname can be nil so it will print Hi Optional("John Appleseed"),

When using ?? always put before it an optional variable but after it a string that is not optional and it will work fine. Hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.