Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using nil-coalescing operator with try? for function that throws and returns optional

I want to use nil-coalescing operator to set a default value in both the following cases:

  1. function throws an error
  2. function returns nil

Please take a look at the code snippet below. I have the following questions:

  1. Why is item1 nil?
  2. What is the difference between the initialization of item1 vs item2
enum VendingMachineError: Error {
    case invalidCode
}

class VendingMachine {
    func itemCode(code: Int) throws -> String? {
        guard code > 0 else {
            throw VendingMachineError.invalidCode
        }
        if code == 1 {
            return nil
        } else {
            return "Item #" + String(code)
        }
    }
}

let machine = VendingMachine()

// Question: Why is this nil?
let item1 = try? machine.itemCode(code: 0) ?? "Unknown"
print(item1)
// nil

// What is the difference between the initialization of item1 vs item2
let item2 = (try? machine.itemCode(code: 0)) ?? "Unknown"
print(item2)
// Unknown

like image 291
Raunak Avatar asked Oct 14 '25 17:10

Raunak


1 Answers

Essentially, this has to do with the grammar of the try operator. When used with a binary expression without brackets, try applies to the whole binary expression, so this:

try? machine.itemCode(code: 0) ?? "Unknown"

is the same as:

try? (machine.itemCode(code: 0) ?? "Unknown")

Since itemCode throws an error, the latter part of the expression ?? "Unknown is ignored, and the try? expression evaluates to nil.

On the other hand, the second expression is like this:

(try? machine.itemCode(code: 0)) ?? "Unknown"

The try? expression is evaluated first (to nil), then the ?? is applied, evaluating the whole expression to "Unknown".

like image 187
Sweeper Avatar answered Oct 17 '25 05:10

Sweeper



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!