添加两个共享相同标识符的枚举

byt*_*nit 8 raku

是否可以在 raku 中定义两个共享相同标识符的枚举?

例如,如果我有以下代码:

#!/usr/bin/raku
use v6;

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

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

您可以在这里看到,标识符 Red 是枚举颜色和枚举 TrafficLight 的一部分。

但是当我执行这个脚本时,我得到了重新声明异常:

$ ./test.p6
Potential difficulties:
    Redeclaration of symbol 'Red'
    at /home/martin/mnt/release-notes/./scripts/test.p6:5
    ------> enum TrafficLight <Red Green>?;

Usage:
  ./scripts/test.p6 -c|--color=<Color> (Blue Red) -t|--traffic-light=<TrafficLight> (Green Red)

    -c|--color=<Color> (Blue Red)                    the color
    -t|--traffic-light=<TrafficLight> (Green Red)    the traffic-light
Run Code Online (Sandbox Code Playgroud)

有趣的是,当我使用参数执行此脚本时-c=Blue and -t=Red,输出是我所期望的:

$ ./test.p6 -c=Blue -t=Red
Potential difficulties:
    Redeclaration of symbol 'Red'
    at /home/martin/mnt/release-notes/./scripts/test.p6:5
    ------> enum TrafficLight <Red Green>?;
Selected Blue, Selected Red
Run Code Online (Sandbox Code Playgroud)

但是,当我使用参数执行此脚本时-c=Red and -t=Green,它根本不起作用,并返回错误代码 2(显示帮助消息)。

我现在的问题是:

  • 是否可以定义两个具有相同名称(但类型不同)的相同 Enum-Identifiers。也许可以在 C++ 中定义一个类似于类枚举的枚举,并namespace围绕它们?
  • 是否有可能以某种方式捕获此异常?

谢谢

use*_*601 11

问题是枚举在其范围内创建符号。你的代码

enum Color <Red Blue>;
enum TrafficLight <Red Green>;
Run Code Online (Sandbox Code Playgroud)

基本上是在做

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>;
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到是什么产生了警告——您不能再创建符号两次,而不能$x在同一范围内声明两次。尽管如此,这两个枚举类仍然存在,并且可以从字符串“Red”创建值。我在这种情况下使用的一种解决方案是创建一个包并调用包内的枚举: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"
}
Run Code Online (Sandbox Code Playgroud)

如果您想匹配值,那么您只需说Color::Redor TrafficLight::Green,或者如果您将内容存储在模块中以便您可以use,您仍然可以仅使用Redor 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"

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

    { # separate new scope 
        use MyEnums::TrafficLight;
        ... 
    }
}
Run Code Online (Sandbox Code Playgroud)