http://www.perlmonks.org?node_id=174655

laughingboy has asked for the wisdom of the Perl Monks concerning the following question:

I've just started defining constants with "use constant", and I'm seeing some, er, non-intuitive behavior. :-)

Here is a code snippet and its output:

use strict; BEGIN { use constant ROTATE => 1; use constant HOLD => 2; use constant FLASH => 3; use constant NUM_MODES => 3; # etc... } my %modestring = ( ROTATE => "a", HOLD => "b", FLASH => "c", # etc... ); my $mode = int(rand NUM_MODES) + 1; print "random mode string is ", $modestring{$mode} || "empty", "\n"; + print "string for 1 is ", $modestring{1} || "empty", "\n"; print "string for ROTATE is ", $modestring{ROTATE} || "empty", "\n"; + random mode string is empty string for 1 is empty string for ROTATE is a
I fixed the problem by using "," instead of "=>" when ititializing the hash, but I don't understand why the code doesn't work as written. Since the constant definitions are in a BEGIN block, shouldn't their values be substituted throughout the source before the hash is initialized?

laughingboy

Replies are listed 'Best First'.
Re: Behavior of compile-time constants?
by Abigail-II (Bishop) on Jun 14, 2002 at 17:58 UTC
    No. Constants aren't substitutions like C-preprocessor macros are. If you use =>, it's left hand side will be autoquoted if the left hand side looks like an identifier. Barewords are valid identifiers, and that's what you have here. So, either use a comma, preceed ROTATE with the (no-op) unary plus, put parens after ROTATE, or something else such that it isn't a bareword anymore.

    Doing use inside a BEGIN is not needed, as use itself happens at compile time.

    Abigail

Re: Behavior of compile-time constants?
by Chmrr (Vicar) on Jun 14, 2002 at 18:00 UTC

    => quotes the lefthand side. Thus, perl is trying to DWIM, and interpreting what you wrote as:

    my %modestring = ( 'ROTATE', "a", 'HOLD' , "b", 'FLASH' , "c", # etc... );

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

Re: Behavior of compile-time constants?
by perrin (Chancellor) on Jun 14, 2002 at 17:59 UTC
    Don't use the constant pragma. It will 'constant'ly trip you up with problems like this. Use ordinary variables in all caps instead.

    The reason your code is breaking is that '=>' stringifies the left argument. The constants are actually implemented as subroutines, and they are not being called. You can fix this by saying "ROTATE() =>" instead of "ROTATE =>", but why bother? Just use variables.

      Don't use the constant pragma
      what? personally, i dislike use constant, so i don't use it. but there is no reason not to use it in this case. as Abagail-II stated above, fix the context and the problem is gone.

      here's an example (my formatting)

      use constant ROTATE => 1; use constant HOLD => 2; use constant FLASH => 3; use constant NUM_MODES => 3; # etc. my %modestring = ( +ROTATE => "a", +HOLD => "b", +FLASH => "c", # etc... );
      since i mentioned my dislike of the constant module (pragma?), i'll describe my solution:

      sub ROTATE () { 1 } # etc. my %modestring = ( +ROTATE => a, # etc. );

      ~Particle *accelerates*

        Since all use constant does is creating such subs, I wonder why you dislike the constant module.

        Abigail, author of the variable pragma.

        That's just it: you shouldn't have to fix the context. Knowing you have to fix the context means knowing how the constant pragma is implemented, and that's not something you should need to know.