2009-01-23 164 views
51

Perl有一个枚举类型,它遵循最佳实践,或者更重要的是,它是否需要一个?Perl有枚举类型吗?

我正在使用的项目使用遍布各处的字符串来表示通常使用C#语言中的Enum的东西。例如,我们在哈希的数组,每个电话类型相关的一组电话号码(“家”,“工作”,“手机”等):

$phone_number->{type} = 'Home'; 

难道是足够在这里使用只读变量集合还是应该使用Enum?我找到了一个enum module on CPAN,但它似乎使用了违反Perl Best Practices之一的裸词。我使用read-only variables的思维是这样的:

use Readonly; 

Readonly my $HOME => 'Home'; 
Readonly my $WORK => 'Work'; 
Readonly my $MOBILE => 'Mobile'; 

$phone_number->{type} = $HOME; 

这是一个很好的方法,或是否有更好的办法?

回答

39

不,没有内建的枚举结构。 Perl并没有做很多严格的输入,所以我认为实际上很少需要一个。

在我看来,你使用的Readonly方法是可靠的。

还有更传统的编译指示。

use constant { 
    HOME => 'Home', 
    WORK => 'Work', 
    MOBILE => 'Mobile', 
}; 

$phone_number->{type} = HOME; 

在幕后,它为每个返回值的常量设置一个函数,如下所示。

sub HOME() { 'Home' } 

我会用Readonly坚持,除非你想利用该特性的优势,例如:

package Phone::Type; 

use constant { 
    HOME => 'Home', 
    #... 
}; 

package main; 

print Phone::Type->HOME, "\n"; 
+0

严格来说,在场景后面有sub HOME(){'home'}。 – 2009-01-26 13:21:55

+0

当你有一个子程序,其中Phone :: Type枚举为参数,你如何执行子程序参数的动态检查是Phone :: Type类型枚举,不是字符串,不是数字... – 2009-06-25 10:13:52

+0

只是为了澄清sub HOME( ){'home'}并使用常数{HOME}>'Home', WORK =>'Work', MOBILE =>'Mobile', }; 是一样的吗?后来生成(幕后)代码? – 2010-01-18 18:18:17

8

你的方式是绰绰有余。

如果您碰巧使用了Moose,您还可以使用Moose :: Util :: TypeConstraints创建枚举。 (你应该这样做)。

17

的Perl事实上确实有一个枚举类型类似于C试试这个了解详情。

perldoc enum

例如:

use enum qw(HOME WORK MOBILE); 

现在我们有:

HOME == 0 
WORK == 1 
MOBILE == 2 

您还可以设置的indeces自己:

use enum qw(HOME=0 WORK MOBILE=10 FAX); 

现在我们有:

HOME == 0 
WORK == 1 
MOBILE == 10 
FAX == 11 

查看here了解更多详情。

请注意,Perl的每个版本都不支持此功能。我知道v5.8.3不支持它,而v5.8.7则支持。

2

你应该永远记住,PBP是咨询 - 书本身。你需要解释准则,而不是一味地采用它们。

5

恐怕Perl是完全截瘫,当谈到这些枚举和命名的常量:

  • 枚举和只读不是核心模块(至少在perl的5.8,这我只是检查)。所以这些可能在没有自由安装新模块的系统上不可用。

  • “使用常数”与“使用严格的”(其中之一应该总是使用)是完全不可用,因为它会产生以下形式的可怕的错误消息的负载:

    裸词“FRED”不允许而“严格潜艇”使用

让我们希望他们在Perl 6中整理出这个烂摊子,如果以往任何时候都看到了曙光!

0

这很好地为我工作...

use constant MYENUM => qw(ZERO ONE TWO THREE FOUR); 

BEGIN { 
    eval "use constant (MYENUM)[$_] => $_;" foreach 0..(MYENUM)-1; 
} 

然后可以使用ZERO, ONE, TWO等为常数,并使用(MYENUM)[$value]打印出自己的符号名。