1

I have been trying to mix custom associated values with String in an Enum but not able to do so. When I try to apply a switch case over the enum, I get this error: Expression pattern of type 'Fruit' cannot match values of type 'Fruit'

Is it because Strings are value types and hence Swift is able to compare them but not custom class object of Fruit which is a reference type?

class Fruit{
    let name: String?
    let energyKcl: Double?
    let costPerKg: Double?

    init(name:String, energyKcl: Double, costPerKg: Double) {
        self.name = name
        self.energyKcl = energyKcl
        self.costPerKg = costPerKg
    }
}

enum Calorie {
    case fruit(Fruit)
    case chocolate (String)
    case dairy(String)
    case Nuts(String)
}


let banana = Fruit.init(name: "Banana", energyKcl: 100, costPerKg: 10)

func prepareBreakfast(calories: Calorie){
    switch calories {

    case .chocolate("Dark"):
        print("Dark")

    case .chocolate("White"):
        print("White")

    case .fruit(banana): //Error: Expression pattern of type 'Fruit' cannot match values of type 'Fruit'
        print("banana")

    default:
        print ("Not available")
    }
}

prepareBreakfast(calories: .fruit(banana))
3
  • 1
    Type should be Equatable for pattern matching. Commented May 21, 2019 at 15:22
  • 1
    I'm not sure what the idea behind Calorie is, but it looks like it would be more appropriately modelled as a protocol with several conforming classes. This enum looks like the kind of thing you want to be able to expand in the future, and polymorphism does that better than tacking on new switch cases everywhere it's used. Commented May 21, 2019 at 15:31
  • Unrelated but why are all properties optional? They are constants and clearly initialized with non-optional values. The code compiles even without question marks. And you would get the == operator for free if Fruit was a struct and adopted Equatable Commented May 21, 2019 at 16:36

3 Answers 3

2

No the problem is that custom class isn't comparable without Equatable protocol

extension Fruit: Equatable {

    static func == (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs.name == rhs.name
        && lhs.energyKcl == rhs.energyKcl
        && lhs.costPerKg == rhs.costPerKg
    }

}
Sign up to request clarification or add additional context in comments.

Comments

1

Pattern matching uses Equatable internally, so you should change your Fruit class:

extension Fruit: Equatable {
    static func == (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs.name == rhs.name // or every field if you want
    }
}

If you want to use the reference, simply change the == func to return true if both references are equal, but I don't think it's a good idea:

static func == (lhs: Fruit, rhs: Fruit) -> Bool {
    return lhs === rhs
}

Comments

0

In your code,

Replace the below line in prepareBreakfast(calories:) method,

case .fruit(banana):

with

case .fruit(let banana):

And you are good to go. I don't think there is any other issue with your code. It is working perfectly fine at my end.

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.