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

Hi, I'm having some problems with the use of constants. I want to know if the way perl handle constants are similar the way C handles defines (#define CONST 10, for example). This code shows my problem:
#!/usr/bin/perl use strict; use warnings; use constant CONST1=>10; use constant CONST2=>12; my %var=( CONST1=>'test1', CONST2=>'test2', ); print $var{CONST1}."\n"; print $var{10}."\n";
It prints:
bash-2.05b$ perl test.pl test1 Use of uninitialized value in concatenation (.) or string at test.pl l +ine 13.
Isn't that supposed to print "test1" in the second print ?

thanks,

DBC

Replies are listed 'Best First'.
Re: Question related to the use of constants
by Aristotle (Chancellor) on Aug 20, 2004 at 17:43 UTC

    What you intended to be constant names are getting parsed as literal strings.

    use strict; use warnings; use constant CONST1=>10; use constant CONST2=>12; my %var=( CONST1=>'test1', CONST2=>'test2', ); use Data::Dumper; print Dumper \%var; __END__ $VAR1 = { 'CONST1' => 'test1', 'CONST2' => 'test2' };

    Internally, constants are functions. You can force them to be recognized by using function syntax:

    my %var=( CONST1()=>'test1', CONST2()=>'test2', ); print $var{CONST1()}."\n"; print $var{10}."\n"; use Data::Dumper; print Dumper \%var; __END__ test1 test1 $VAR1 = { '10' => 'test1', '12' => 'test2' };

    Or, as I personally prefer:

    my %var=( (CONST1)=>'test1', (CONST2)=>'test2', ); print $var{(CONST1)}."\n"; print $var{10}."\n";

    Makeshifts last the longest.

      danielcid, just to clarify the parent post a little,

      The '=>' operator treats barewords on the left hand side as a string, and CONST1 is a bareword. Changing

      CONST1 => 'test1'

      to any of the following will work:

      (CONST1) => 'test1' # No longer a bareword. CONST1() => 'test1' # constants are really special functions. CONST1, 'test1' # use "," instead of "=>". It's the same, # except it doesn't quote the LHS.
Re: Question related to the use of constants
by hardburn (Abbot) on Aug 20, 2004 at 17:53 UTC

    I want to know if the way perl handle constants are similar the way C handles defines

    Nope. Perl handles them (more or less) the way more recent C compilers handle inline functions. When you use constant FOO => 1;, a subroutine is created in your current package like this:

    sub FOO () { 1 }

    That sort of subroutine (note empty prototype and simple return value) will be considered for inlining. You can then use it anyplace you could put a subroutine, which does not include string interpolation (which is what hash lookups are).

    OTOH, a #DEFINE in C is done by the preprocessor, which modifies the source code before the compiler does anything with it.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      (which is what hash lookups are).
      That's just wrong. The only thing special about hash look ups are that barewords are special cased to be treated as a string.
      sub foo { "test" } $hash{ foo } = 32; #the literal string "foo" is used as the key $hash{ foo() } = 45; #the string "test" is used $x='te'; $y='st'; $hash{ $x$y } = 32; #this is a syntax error, because it's not string i +nterpolation
Re: Question related to the use of constants
by haoess (Curate) on Aug 20, 2004 at 17:44 UTC
    Isn't that supposed to print "test1" in the second print ?

    No. If you create a hash key using a bareword, it will be treated as if it was a quoted string. Use $hash{ &KEY } = $value to get your constants work.

    -- Frank

Re: Question related to the use of constants
by ysth (Canon) on Aug 20, 2004 at 18:09 UTC
    In a hash element lookup, if what's in the { } is something that follows the rules for identifier names, it is interpreted as just a string, not a function call, a builtin, a constant or whatever. So $x{CONST1} is $x{"CONST1"}, not $x{10}.

    There are various ways to make this work; I like $x{+CONST1}. (Yes, that works even for constants that have non-digits, leading zeros, whatever.)

    Sometimes the reverse gotcha happens: $x{0001} is $x{1}, not $x{"0001"}, because 0001 is not an valid identifier. (Hmm, $0001 seems to work, when it shouldn't according to perldata.)   Another strange case is $x{a'b} which is actually $x{"a::b"), because ' is the old way of saying ::.

Re: Question related to the use of constants
by Prior Nacre V (Hermit) on Aug 20, 2004 at 22:16 UTC

    After declaring your constants, you should use the following syntax where indicated:

    As a hash key
    $hash{+CONST} or
    $hash{CONST()}
    Lefthand side of => operator
    ... CONST() => $value ... (+CONST won't work here)
    Interpolation in a string
    print "My CONST = @{[CONST]}\n"

    The constant manpage explains why.

    Regards,

    PN5

Re: Question related to the use of constants
by danielcid (Scribe) on Aug 20, 2004 at 19:05 UTC
    Thanks for the help! Everyday learning a little bit more.. :)

    -DBC