Swift optional in case where statement

326 Views Asked by At

Doing a course the other day and one of the attendants tried something out and it came up with an interesting bug.

How can this provide an result when it is switching on a case with value nil?

func canDrink(age: Int?, country: String)->bool{
    switch (age, country){
    case (let anAge, _) where anAge < 5: //playground still says anAge is an optional
        return false
    default:
        return true
    }
}
canDrink(15,"UK")  // Returns true
canDrink(4,"UK")   // Returns false
canDrink(nil,"UK") // Also returns false not an error.

Cheers

1

There are 1 best solutions below

4
On BEST ANSWER

Update

To provide a bit more context, per your comment. There is nothing invalid about comparing against an optional:

var d: Int? = 4
if d < 5 {} // true

and if the optional is nil it will still be a true value:

var d: Int? = nil
if d < 5 {} // still true

Why is this? Well a nil value is literally .None (if .None < 5) (see below) and in this case 5 is definitely greater than .None.

Original

The problem here is that let anAge is an optional Int (as you pointed out). If you inspect it you will see this (image for reference):

enter image description here

If you take a look at the optional definition you will see an option is an enum with two types (None and Some). So we can just check against Some to make sure it has a value:

func canDrink(age: Int?, country: String) -> Bool {
    switch (age, country) {
    case (.Some, _) where age < 5: // We now know that `age` is some value
        return false
    default:
        return true
    }
}

canDrink(15,"UK")  // Returns true
canDrink(4,"UK")   // Returns false
canDrink(nil,"UK") // Now returns true, since this is a `.None` age