Reputation: 42776
Building off Does Perl have an enumeration type?, how can I perform dynamic type checking (or static type checking if use strict is able to do so) that my subroutine argument is getting the right type of enum?
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
Upvotes: 3
Views: 1640
Reputation: 98398
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
(The BEGIN is necessary to set $types at compile time so that it's available to the use statement.)
It's fairly common in Perl to be relaxed about things like this; to just assume that functions are passed numbers where you expect numbers, etc. But if you want to do this kind of validation, you may be interested in Params::Validate.
Upvotes: 2
Reputation: 7143
I would suggest that you use Readonly (as suggested in the referenced question) rather than constant. I'd suggest on of two possible approaches (depending on if you are using Perl 5.10 or 5.8).
Initially, the same code:
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;
# ...
}
There is a module on CPAN which will allow you to have a great deal of control over argument types and values but I can't for the life of me remember it. Perhaps someone else can.
Upvotes: 3
Reputation: 118156
Here is one way:
#!/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
Upvotes: 4