Here’s an example that Apple provided in The Swift Programming Language. Please take a few moments to read the code so I can explain my question, sorry if it’s a bit long.
enum VendingMachineError: Error{
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemName name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing \(name)")
}
}
Note that the first guard let statement inside the vend method assigns the value of inventory[name] to a constant called item.
And towards the end of the vend method’s definition, the item constant’s value is assigned to a newly created variable called newItem . I understand that the reason why this newItem variable is declared is because Apple wants to change the count property of item, but that’s impossible because item is a constant, therefore the newItem variable is created to do that.
But I found an easier way to write the above code without creating a newItem. Instead of assigning the value of inventory[name] to a constant, I assign it to a variable. Here’s my modified version of the code:
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemName name: String) throws {
guard var item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
item.count -= 1
inventory[name] = item
print("Dispensing \(name)")
}
}
So, instead of guard let item = inventory[name], I wrote guard var item = inventory[name]. In the hope that the value of inventory[name] gets assigned to a variable, instead of a constant. This way I can just change the count property of the item variable without having to create a separate newItem variable to modify the count property like Apple did.
My question is, is there a reason why Apple uses guard let instead of guard var? Guard var is never used in The Swift Programming Language. I’m worried that there might be unwanted consequences of using guard var that I’m not aware of.