3

Trying to access the value of a double-nested enum in Swift that is passed in as a parameter to the first enum. I'm not sure how to access the CutStyle; within the for loop in shareSalad, each ingredient that is iterated over does not have a .dot accessor except self. I.e. there is no ingredient.cut or ingredient(cut) available.

I'm confused on how to access CutStyle

import Cocoa

enum Ingredients {
    case lettuce(cut: CutStyle)
    case tomatoes(cut: CutStyle)
    case onions(cut: CutStyle)
    case cucumbers(cut: CutStyle)
    case dressing
    
    enum CutStyle {
        case diced
        case chopped
        case minced
        case grated
    }
}

var salad: [Ingredients] = []

func makeSalad(with ingredient: Ingredients) {
    switch ingredient {
    case .lettuce(let cut):
        salad.append(.lettuce(cut: cut))
    case .tomatoes(let cut):
        salad.append(.tomatoes(cut: cut))
    case .onions(let cut):
        salad.append(.onions(cut: cut))
    case .cucumbers(let cut):
        salad.append(.cucumbers(cut: cut))
    case .dressing(let cut):
        salad.append(.dressing(cut: cut))
    }
}

func shareSalad(my salad: [Ingredients]) {
    print("My salad contains:")
    for ingredient in salad {

        // Q: How to access the ingredient CutStyle here?
        print(ingredient)
    }
}

makeSalad(with: .cucumbers(cut: .chopped))
makeSalad(with: .onions(cut: .diced))
makeSalad(with: .tomatoes(cut: .minced))

shareSalad(my: salad)

/*
My salad contains:
cucumbers(cut: __lldb_expr_29.Ingredients.CutStyle.chopped)
onions(cut: __lldb_expr_29.Ingredients.CutStyle.diced)
tomatoes(cut: __lldb_expr_29.Ingredients.CutStyle.minced)
*/
Elliot
  • 83
  • 7
  • I think [this](https://stackoverflow.com/a/37159851/14351818) might be helpful... I've never come across using enums this way though. Very interesting. – aheze Feb 06 '21 at 02:22
  • 1
    Thank, it does help a bit. I think where I'm getting confused is because there are multiple cases in the second-level enum, so maybe I have to make a `value` and `return` statement for each, as in your linked post. – Elliot Feb 06 '21 at 02:46

1 Answers1

1

You would need a giant switch statement to extract the cut styles,

for ingredient in salad {
    let cutStyle: CutStyle?
    switch ingredient {
    case .lettuce(let cut):
        cutStyle = cut
    case .tomatoes(let cut):
        cutStyle = cut
    case .onions(let cut):
        cutStyle = cut
    case .cucumbers(let cut):
        cutStyle = cut
    case .dressing:
        cutStyle = nil
    }
    print(cutStyle)
}

I think you could have modelled your salad better. Here are two alternative designs that allows you to access the cut style more easily.

One way is to make a SaladIngredient struct that composes a cut style and an ingredient:

struct SaladIngredient {
    enum Ingredient {
        case lettuce
        case tomatoes
        case onions
        case cucumbers
        case dressing
    }

    enum CutStyle {
        case diced
        case chopped
        case minced
        case grated
    }

    let ingredient: Ingredient
    let cutStyle: CutStyle?
}
func shareSalad(my salad: [SaladIngredient]) {
    print("My salad contains:")
    for ingredient in salad {
        if let cutStyle = ingredient.cutStyle {
            print(cutStyle)
        }
    }
}

The disadvantage of this is that it's harder to enforce the rule that dressings don't have a cut style.

Alternatively, collapse all those enum cases with a cut style into one case:

enum SaladIngredient {
    enum Ingredient {
        case lettuce
        case tomatoes
        case onions
        case cucumbers
    }
    enum CutStyle {
        case diced
        case chopped
        case minced
        case grated
    }
    case cuttable(Ingredient, cutStyle: CutStyle)
    case dressing
}
func shareSalad(my salad: [SaladIngredient]) {
    print("My salad contains:")
    for ingredient in salad {
        if case .cuttable(_, cutStyle: let cutStyle) = ingredient {
            print(cutStyle)
        }
    }
}

The disadvantage of this is that you are making .dressing a totally different "type" of thing from lettuce, tomatoes and others.

Sweeper
  • 213,210
  • 22
  • 193
  • 313