是否可以在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"
}
在这里您可以看到,标识红色是枚举颜色和枚举TrafficLight的一部分。
但是当我执行此脚本时,我得到了Redeclaration-exception:
$ ./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
有趣的是,当我使用参数-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
但是当我使用参数-c=Red and -t=Green
执行此脚本时,它根本无法工作,并且返回错误代码2(显示帮助消息)。
我的问题现在是:
namespace
包围它们?谢谢
答案 0 :(得分:11)
问题在于枚举会在其范围内创建符号。您的代码
enum Color <Red Blue>;
enum TrafficLight <Red Green>;
基本上在做
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>;
因此,您可以看到生成警告的原因-在相同的作用域中,创建符号的次数不能超过两次声明$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"
}
如果要与值匹配,则只需说Color::Red
或TrafficLight::Green
,或者如果将内容存储在模块中以便可以use
,则仍然可以使用只是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"
{ # new scope
use MyEnums::Color;
given $color {
when Red { ... }
when Green { ... }
}
}
{ # separate new scope
use MyEnums::TrafficLight;
...
}
}
答案 1 :(得分:1)
如果只希望导出枚举而不导出枚举中的值,则可以将constant
与do
块一起使用。
constant Color = do {
my enum Color <Red Blue>;
Color
}
constant Traffic-Light = do {
my enum Traffic-Light <Red Green>;
Traffic-Light
}
这样做,您只需要按其完全限定的名称或通过哈希访问来访问枚举中的值。
say Color::Red.raku;
say Traffic-Light::Red.raku;
say Color::{'Red'}.raku;
say Traffic-Light::{'Red'}.raku;
say Red; # ERROR: Undeclared name: Red
multi foo ( Color $c ){
say "the color $c"
}
multi foo ( Traffic-Light::Red ){
say "stop"
}
multi foo ( Traffic-Light::Green ){
say "go"
}
multi foo ( Str $s ){
samewith Traffic-Light::{$s} // Color::{$s}
}
foo Color::Red; # the color Red
foo Color::Blue; # the color Blue
foo Traffic-Light::Red; # stop
foo Traffic-Light::Green; # go
foo 'Green'; # go
foo 'Red'; # stop
foo 'Blue'; # the color Blue