如何验证枚举类型为Perl子例程参数?

时间:2009-06-25 10:28:45

标签: perl enums validation subroutine

建立Does Perl have an enumeration type?,如何执行动态类型检查(或者如果use strict能够执行静态类型检查)我的子例程参数是否获得了正确的枚举类型?

package Phone::Type;

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

package main;

sub fun
{
    my ($my_phone_type_enum) = @_;
    # How to check my_phone_type_enum, is either Phone::Type->HOME or Phone::Type->WORK or ... but not 'Dog' or 'Cat'?
}

fun(Phone::Type->HOME); # valid
fun(Phone::Type->WORK); # valid
fun('DOG');             # run-time or compile time error

3 个答案:

答案 0 :(得分:4)

这是一种方式:

#!/usr/bin/perl

package Phone::Type;

use strict;
use warnings;

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

package main;

use strict;
use warnings;

sub fun {
    my ($phone_type) = @_;
    Phone::Type->can( $phone_type )
        or die "'$phone_type' is not valid\n";
}

fun('HOME'); # valid
fun('WORK'); # valid
fun('DOG');  # run-time or compile time error
__END__

C:\Temp> dfg
'DOG' is not valid

答案 1 :(得分:3)

我建议您使用Readonly(如引用的问题所示)而不是常量。我建议采用两种可能的方法(取决于你使用的是Perl 5.10还是5.8)。

最初,相同的代码:

use strict;
use warnings;
use Readonly;

Readonly my @phone_types = qw/HOME WORK/;

Perl 5.10:

sub fun
{
   my $type = shift;
   die "Invalid phone type: $type" unless $type ~~ @phone_types;
   # ...
}

Perl 5.8:

sub fun
{
   my $type = shift;
   die "Invalid phone type: $type" unless grep { $_ eq $type} @phone_types;
   # ...
}

CPAN上有一个模块可以让你对参数类型和值有很大的控制权,但我不能记住它。也许其他人可以。

答案 2 :(得分:2)

package Phone::Type;

my $types;
BEGIN {
    $types = {
        HOME => 'Home',
        WORK => 'Work',
    };
}
use constant $types;

sub is_phone_type {
    my ($type) = @_;
    return exists $types->{$type};
}

package main;
use Carp ();

sub fun
{
    my ($my_phone_type_enum) = @_;
    Phone::Type::is_phone_type( $my_phone_type_enum)
        or Carp::croak "Invalid type $my_phone_type_enum";
}

fun(Phone::Type->HOME); # valid
fun(Phone::Type->WORK); # valid
fun('DOG');             # run-time or compile time error

(BEGIN是在编译时设置$ types所必需的,因此它可用于use语句。)

在Perl中,对这样的事情放松是很常见的;假设函数是传递数字的数字,等等。但是如果你想进行这种验证,你可能会对Params::Validate感兴趣。