1

Hi I'm trying to learn Swift using Apples Fundamentals of Swift book. There has been a similar post in the past but I have some problems with the answer provided that I would like clarified.

The post was Functions and optionals exercise

I'm on this exercise where you are supposed to print the return value. The return value being either nil if the stock of the item is 0 or the price if the stock is not 0. To add I thought the point was to unwrap the price value if you return it instead of nil. In earlier exercises they had us unwrap the optionals.

var prices = ["Chips": 2.99, "Donuts": 1.89, "Juice": 3.99, "Apple": 0.50, "Banana": 0.25, "Broccoli": 0.99]
var stock = ["Chips": 4, "Donuts": 0, "Juice": 12, "Apple": 6, "Banana": 6, "Broccoli": 3]

var prices = ["Chips": 2.99, "Donuts": 1.89, "Juice": 3.99, "Apple": 0.50, "Banana": 0.25, "Broccoli": 0.99]
var stock = ["Chips": 4, "Donuts": 0, "Juice": 12, "Apple": 6, "Banana": 6, "Broccoli": 3]

func purchase(item: String) -> Double? {
    stock[item]! == 0 ? nil : prices[item]
}
    
print(purchase(item: "Chips"))

If I print(purchases(item: "Chips") I get printed optional(2.99). If it was unwrapped wouldn't it just be 2.99? I could cheat when I call the function and force unwrap but that ruins the point.

When I do try to safely unwrap I get a message saying "Missing return in a function expected to return 'Double?'"

As so:

var prices = ["Chips": 2.99, "Donuts": 1.89, "Juice": 3.99, "Apple": 0.50, "Banana": 0.25, "Broccoli": 0.99]
var stock = ["Chips": 4, "Donuts": 0, "Juice": 12, "Apple": 6, "Banana": 6, "Broccoli": 3]

func purchase(item: String) -> Double? {
    if stock[item]! == 0 {
        return nil
    } else {
        if let itemPrice = prices[item] {
            return itemPrice
        }
    }
}

I could add another else return nil after the if let statement but then I'm back to having a wrapped optional.

Thanks for any answers

JGW
  • 43
  • 1
  • 6
  • If you return `Double` instead of `Double?`, then it will print without `optional`, but you have to safely unwrap it using `if let` or `guard let`. – Rob Nov 03 '20 at 07:17
  • As I understand it, the exercise does not require you to return an unwrapped optional in `purchase`. Your first implementation is correct (disregarding the force-unwrapping). – Sweeper Nov 03 '20 at 07:19
  • "To add I thought the point was to unwrap the price value if you return it instead of nil." I think you are overthinking. You don't need to unwrap the price, because the function is returning a wrapped optional anyway. – Sweeper Nov 03 '20 at 07:21
  • This is a pretty unrealistic exercise. In the real world you would create a struct which contains all information about one object – vadian Nov 03 '20 at 08:36

2 Answers2

1

There are many ways to unwrap a value. You can try these ways.

1. The first way:

guard let value = purchase(item: "Chips") else { return }
   print(value)

2. The second way:

if let value = purchase(item: "Chips"){
   print(value)
}

3. The third way:

if (purchase(item: "Chips") != nil){
   print(purchase(item: "Chips")!)
}
Solayman Rana
  • 283
  • 3
  • 12
Carson Vo
  • 476
  • 6
  • 20
0

You can't unwrap in the function. The function returns an optional; that is the specification you are given.

Since the function returns an optional, you can't simply print the return value (well, you can, but you get "optional(2.99)" ).

First, you can re-write your function to avoid force unwrapping (the specification says that you should pass a string that is in the dictionary, but it is always a good to code defensively).

func purchase(item: String) -> Double? {
   if let qty = stock[item], qty > 0, price = prices[item] {
       return price
   }
   return nil
}

Then you can use the function

if let price = purchase("chips") {
    print("Purchased for $\(price)")
} else {
    print("None in stock")
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186