3

If I have the following enum:

enum FruitTuple
{
    static let Apple = (shape:"round",colour:"red")
    static let Orange = (shape:"round",colour:"orange")
    static let Banana = (shape:"long",colour:"yellow")
}

Then I have the following function:

static func PrintFruit(fruit:FruitTuple)
{
    let shape:String = fruit.shape
    let colour:String = fruit.colour

    print("Fruit is \(shape) and \(colour)")
}

On the fruit.shape and fruit.colour I get the error:

Value of type 'FruitTuple' has no member 'shape'

Fair enough, so I alter the enum to have a type:

enum FruitTuple:(shape:String, colour:String)
{
    static let Apple = (shape:"round",colour:"red")
    static let Orange = (shape:"round",colour:"orange")
    static let Banana = (shape:"long",colour:"yellow")
}

But then on the enum declaration I get the error:

Inheritance from non-named type '(shape: String, colour: String)'

So, the question is: Is it even possible to have a tuple in an enum and be able to reference it's component parts in such a way? Am I just missing something fundamental here?

Wex
  • 4,434
  • 3
  • 33
  • 47
  • 2
    `FruitTuple.Apple` etc are just tuples, they are *not* enum values (you did not define any `case`s). `enum FruitTuple` only provides a "namespace" (as in https://stackoverflow.com/questions/38585344/swift-constants-struct-or-enum) – Martin R Jul 07 '17 at 14:13
  • Related: https://stackoverflow.com/questions/26387275/enum-of-tuples-in-swift. – Martin R Jul 07 '17 at 14:18
  • Cheers, that related question helps. The point about namespaces totally makes sense now too! – Wex Jul 07 '17 at 14:23

1 Answers1

5

As pointed out by @MartinR. Also, according to Apple docs, "enumeration cases can specify associated values of any type to be stored along with each different case value". If you want to keep using enum, you may need to do something like:

static func PrintFruit(fruit:FruitTuple.Apple)
{
    let shape:String = fruit.shape
    let colour:String = fruit.colour

    print("Fruit is \(shape) and \(colour)")
}

I'm not certain of what you want, but I guess using typealias could help achieve your goal.

typealias FruitTuple = (shape: String, colour: String)

enum Fruit
{
    static let apple = FruitTuple("round" , "red")
    static let orange = FruitTuple("round", "orange")
    static let banana = FruitTuple("long", "yellow")
}

func printFruit(fruitTuple: FruitTuple)
{
    let shape:String = fruitTuple.shape
    let colour:String = fruitTuple.colour
}
Lawliet
  • 3,438
  • 2
  • 17
  • 28
  • 1
    When you start using a type alias for a tuple, it's probably time for a struct – Alexander Jul 07 '17 at 14:42
  • @Alexander Normally, if I have <=2 properties, I use tuple (w/ or w/o `typlealias`) to simplify the code with no need of constructors and customised equatable function. Could you pls point me out with the right direction why should I use struct in this case? – Lawliet Jul 07 '17 at 15:06
  • 2
    Well, you can't use these as Dictionary keys for one, because tuples can't conform to Hashable (or any protocols, for that matter). Also, `Fruit` can be any (`String`, `String`), tuple. My `typealias Person = (firstName: String, lastName: String)` tuple is the same type. I could say: `let p: Person = FruitTuple("round" , "red")`. Though I suppose some people are red, round and fruity, I don't think that's intended. – Alexander Jul 07 '17 at 15:13