Adding two enums that share some same identifiers

The problem is that enum create symbols in their scope. Your code

enum Color <Red Blue>;
enum TrafficLight <Red Green>;

is basically doing

my \Color = Map.new(Red => 0, Blue => 1) does Enumeration;
my \Red  := Color<Red>;
my \Blue := Color<Blue>;

my \Traffic-Light = Map.new(Red => 0, Green => 1) does Enumeration;
my \Red   := Traffic-Light<Red>;
my \Green := Traffic-Light<Green>;

Thus you can see what generates the warning -- you can't create the symbol twice anymore than you can declare $x twice in the same scope. Nonetheless, the two enum classes still exist, and can create values from the string "Red". One solution I've used in this case is to create a package and call the enum inside the package: Enum

package Color        {  enum Enum <Red Blue>   }
package TrafficLight {  enum Enum <Red Green>  }

sub MAIN(
    Color::Enum:D        :c(:$color        )!, #= the color
    TrafficLight::Enum:D :t(:$traffic-light)!, #= the traffic-light
) {
    say "Selected $color, Selected $traffic-light"
}

If you want to match against the values, then you just say Color::Red or TrafficLight::Green, or if you store things in a module so that you can use, you could still use just Red or Green, just not in the same scope. So you could do:

sub MAIN(
    Color::Enum:D        :c(:$color        )!, #= the color
    TrafficLight::Enum:D :t(:$traffic-light)!, #= the traffic-light
) {
    say "Selected $color, Selected $traffic-light"

    { # new scope 
        use MyEnums::Color;
        given $color { 
            when Red   { ... }
            when Green { ... }
        }
    }

    { # separate new scope 
        use MyEnums::TrafficLight;
        ... 
    }
}

Tags:

Raku