Does Perl have an enumeration type?

PerlEnums

Perl Problem Overview


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?

Perl Solutions


Solution 1 - Perl

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";

Solution 2 - Perl

Perl does in fact have an enum type like in C. Try this for details.

[perldoc enum][enum]

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][enum] 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.

[enum]: https://metacpan.org/pod/enum "enum - C style enumerated types and bitmask flags in Perl"

Solution 3 - Perl

Perl doesn't support the concept natively but there are modules to add this functionality

https://metacpan.org/pod/enum

Solution 4 - Perl

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.)

Solution 5 - Perl

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!

Solution 6 - Perl

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].

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncowgodView Question on Stackoverflow
Solution 1 - PerlRonald BlaschkeView Answer on Stackoverflow
Solution 2 - PerlNathan FellmanView Answer on Stackoverflow
Solution 3 - PerlRay BooysenView Answer on Stackoverflow
Solution 4 - PerljrockwayView Answer on Stackoverflow
Solution 5 - PerlJohn RobertsView Answer on Stackoverflow
Solution 6 - PerlkbroView Answer on Stackoverflow