Reputation: 8656
Does Perl have an enumeration type that adheres to best practices, or maybe more importantly, does it need one?
The project I am working one uses strings all over the place to denote things that would typically use an Enum in a language like C#. For example, we have a set of phone numbers in an array of hashes, each associated with a phone type ("Home", "Work", "Mobile", etc.):
$phone_number->{type} = 'Home';
Would it be sufficient to use a read-only set of variables here or should an Enum be used? I've found an enum
module on CPAN but it appears to use bare words which violates one of the Perl Best Practices. My thinking on using read-only variables goes something like this:
use Readonly;
Readonly my $HOME => 'Home';
Readonly my $WORK => 'Work';
Readonly my $MOBILE => 'Mobile';
$phone_number->{type} = $HOME;
Is this a good approach or is there a better way?
Upvotes: 63
Views: 46635
Reputation: 127578
Perl does in fact have an enum type like in C. Try this for details.
For instance:
use enum qw(HOME WORK MOBILE);
Now we have:
HOME == 0
WORK == 1
MOBILE == 2
You can also set the indices yourself:
use enum qw(HOME=0 WORK MOBILE=10 FAX);
Now we have:
HOME == 0
WORK == 1
MOBILE == 10
FAX == 11
Look here for more details.
Note that this isn't supported in every version of Perl. I know that v5.8.3 doesn't support it, while v5.8.7 does.
Upvotes: 29
Reputation: 4991
This worked nicely for me...
use constant MYENUM => qw(ZERO ONE TWO THREE FOUR);
BEGIN {
eval "use constant (MYENUM)[$_] => $_;" foreach 0..(MYENUM)-1;
}
You can then use ZERO, ONE, TWO
etc as constants and print out their symbolic name using (MYENUM)[$value]
.
Upvotes: 0
Reputation: 4184
No, there isn't a built-in enum construct. Perl doesn't do a lot of strict typing, so I think there's actually little need for one.
In my opinion, the Readonly
approach you used is solid.
There's also the more traditional constant
pragma.
use constant {
HOME => 'Home',
WORK => 'Work',
MOBILE => 'Mobile',
};
$phone_number->{type} = HOME;
Behind the scenes, it sets up a function for each constant that returns the value, like so.
sub HOME () { 'Home' }
I'd stick with Readonly
unless you want to take advantage of that property, for example:
package Phone::Type;
use constant {
HOME => 'Home',
#...
};
package main;
print Phone::Type->HOME, "\n";
Upvotes: 47
Reputation: 30031
Perl doesn't support the concept natively but there are modules to add this functionality
Upvotes: 11
Reputation: 75
I'm afraid perl is completely paraplegic when it comes to these enums and named constants:
enum and Readonly are not core modules (at least at perl 5.8, which I just checked). So these may be unavailable on a system where one has no freedom to install new modules.
"use Constant" with "use strict" (which one should always use) is completely unusable, as it generates a load of horrible error messages of the form:
Bareword "FRED" not allowed while "strict subs" in use
Let's hope they've sorted out this mess in perl 6, if that ever sees the light of day!
Upvotes: 5
Reputation: 42684
Your way is more than adequate.
You can also create enums with Moose::Util::TypeConstraints, if you happen to be using Moose. (Which you should be.)
Upvotes: 8