The Everloving Perl's Constant - Part 2

In the previous post, we've look into declaring and using constant within the same module. How about using a constant from other package?

Let's create a sample `FooBar` module (FooBar.pm) which exports a constant, `COLUMNS` as shown below.
package FooBar;

use strict;
use warnings;
use Exporter qw(import);

use constant COLUMNS => qw(TEST1 TEST2 TEST3);
our @EXPORT_OK = qw(COLUMNS);

1;

To use this in another Perl script (test.pl). Notice there are several ways to use and access the `COLUMNS` constant.
use FindBin; # current script path
use lib "$FindBin::Bin"; # append current script path to the Perl's library path
use FooBar 'COLUMNS';

use strict;
use warnings;
use feature 'say';

say FooBar::COLUMNS();
say FooBar->COLUMNS();
say FooBar::COLUMNS;
say (COLUMNS);
say (COLUMNS());

1;

Should we use constant pragma in Perl? No, according to Damian Conway in this book, Perl Best Practices. Instead he advocates that we should "use named constants, but don't use constant."  What he meant if you want to use constant in Perl, use the Readonly module instead of the constant pragma. However, Perl Best Practices was written in 2005, 13 years ago. Hence, which begs the question, does the recommend practices still relevant for these days? Nope, even Modern Perl 4th Edition, published in 2016 also discourages the use of bareword constant.

So, if we still want to use constant in Perl, what is the modern take (as in 2018) on Perl's constant? Discussion at Reddit leads to two Perl modules, Const::Fast or ReadonlyX. I like the former for its speed (even though benchmark results doesn't differ much) and simplicity as shown below (example taken from the module doc).
use Const::Fast;
 
const my $foo => 'a scalar value';
const my @bar => qw/a list value/;
const my %buz => (a => 'hash', of => 'something');

I've read and seen developers who work around this problem by using  scalar through `our`and uppercase to declare variables.
our $COLUMNS = qw(TEST1 TEST2 TEST3);

Some even encapsulate these constants within a subroutine (which is true anyway as constant in Perl is an anonymous subroutine) with predefined values.
sub COLUMNS {
    return qw(TEST1 TEST2 TEST3);
}

Nothing wrong with that as there are developers who don't even want to bother with Perl's caveat. Furthermore, benchmark shows that these two methods, using variable or subroutine, is faster than using constant pragma. Maybe they are right. Perl, a weakly-typed and TMTOWTDI programming language, should be "abused" and treated like one.

In the end, should we even bother? Yes. After the comparison of 21 Perl modules that implement constant (yes, 21 bloody ways and that was written in 2012), it's good to stick to a standard way of using constant in your code base. Be it a constant pragma or Const::Fast module, just stick to one.

No comments:

Post a Comment