Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Perl "Constants"

by zerohero (Monk)
on Jul 07, 2009 at 01:34 UTC ( #777711=perlquestion: print w/ replies, xml ) Need Help??
zerohero has asked for the wisdom of the Perl Monks concerning the following question:

I'd like to have read-only constants which exist in a module that I include. The purpose of the constant is to eliminate "magic numbers", as one would do with a #define in C.

What I've been doing, which has some drawbacks, is to make a module with Exporter and do the following, and then import each constant into the package it's used in.

package MyConstants; use base qw (Exporter); our @EXPORT_OK = qw (SOME_CONSTANT); + use constant SOME_CONSTANT => 'the value';

Is there a better method than this? This suffers the drawback that inside of a hash, it doesn't get interpolated (i.e. $h{SOME_CONSTANT} doesn't behave as one would "like").

Comment on Perl "Constants"
Download Code
Re: Perl "Constants"
by GrandFather (Cardinal) on Jul 07, 2009 at 01:54 UTC

    Readonly may help.

    True laziness is hard work
Re: Perl "Constants"
by tprocter (Sexton) on Jul 07, 2009 at 02:34 UTC

    If you want to continue using constant, and you want to interpolate within a string, the only way I know of is using the array interpolations:

    use constant SOME_CONSTANT => 'the value'; print "This is @{[SOME_CONSTANT]}\n";

    Within a hash key, treat it as a sub:

    $h{&SOME_CONSTANT} = 'hash value';

      For string interpolation you may also use scalar context

      print "This is ${\SOME_CONSTANT}\n";

      With a hash key you can also disambiguate a constant with parens

Re: Perl "Constants"
by perrin (Chancellor) on Jul 07, 2009 at 03:55 UTC
    Forget the constant pragma. The minor speed difference over a variable isn't worth the bugs it causes when you accidentally use it in a context where it doesn't interpolate. Just use $SOME_CONSTANT instead.
Re: Perl "Constants"
by Marshall (Prior) on Jul 07, 2009 at 07:14 UTC
    In 'C', yes there can be many #define statements.

    One way to deal with this in Perl is to say have a .ini file. Stick these "magic" definitions like "MAX_RECS_PER_LINE = 8" in that file. Parsing a .ini file can get to be a pretty big deal in 'C'. In Perl, this is easy as there are a number of "config" modules that do that. At times I have built a "front-end" module that uses some flavor of the configuration .ini modules.

    Anyway one possibility is to have say $MAX_RECS_PER_LINE as a program variable and you ask the config module (really a mini read only DB in simple case) what MAX_RECS_PER_LINE means.

Re: Perl "Constants"
by JavaFan (Canon) on Jul 07, 2009 at 07:19 UTC
    I used to use use constant; because that felt like being the "right" way. But I got annoyed by the constants not behaving like variables you don't modify. (Don't interpolate, can be autoquoted). So, I haven't used use constant; for a long time now. I use variables, whose name I usually uppercase.
      "use constant" is useful for debug statements and levels. In recent versions of Perl, if the compiler can see say "if DEBUG_LEVEL3" and if knows that DEBUG_LEVEL3 is false, that statement will not even be compiled. This can result in a significant performance increase where there are lots of detailed "debug" print statements within an inner loop.

      Other than that, I think use constant is pretty worthless. I normally use a 'C' style $ALL_UPPER_CASE for constants and as a matter of programming discipline, never use something like that as a lvalue.

      I guess that was a long winded way of saying: I agree, but think about constant for debug flags when you have a lot of them or they are in performance critical sections of code.

Re: Perl "Constants"
by Arunbear (Parson) on Jul 07, 2009 at 16:24 UTC
    You can also create a constant like this:
    *SOME_CONSTANT = \ 'the value';
    Then these will be possible:
    $h{$SOME_CONSTANT}; print "$SOME_CONSTANT\n";
    $SOME_CONSTANT = 'new value';
    would die with "Modification of a read-only value attempted at ... ".

    This is documented in perlmod under "Symbol Tables".

      Small problem is that these are package variables (not 'my'-able). Under 'use strict' U have to 'our' them. In case U want the freedom to choose between package or lexical, I use this:
      use CONSTANT; CONSTANT my $E => 2.73, my $PI => 3.14, my $CREDO => 'The dream of the slave become master +and have slaves'; # Oops! Wrong CREDO ;) $CREDO = 'In $$$ we trust!'; # will ERROR out ;) # and U can: print "I still believe that '$CREDO!'\n"; #where package CONSTANT; use Carp; use Exporter; use Tie::Scalar; @ISA = qw(Tie::StdScalar Exporter); @EXPORT = qw(CONSTANT); # sub CONSTANT {my $i=0;tie $_[$i++],__PACKAGE__,$_[$i++] while $i<@_} sub CONSTANT {tie $_[$.++],__PACKAGE__,$_[$.++] while $. < @_} # If you want to know if something is tied somewhere ;) # sub REF {@_ > 1 ? '' : ref tied $_[0] || ref $_[0]} sub STORE {confess "constants are READ ONLY!"}; 1; vess

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://777711]
Approved by AnomalousMonk
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2014-12-18 01:03 GMT
Find Nodes?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?

    Results (41 votes), past polls