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

Why does the execution of the following script print the string MELHARRIS on the last line? I expected perl to evaluate HARRIS, because it evaluated EARL.
#!/usr/bin/perl -w use strict; use CGI qw/:standard/; use constant EARL => 'MEL'; use constant HARRIS => 'BROOKS'; my @a = map { lc($_) } (EARL, HARRIS); my $b = { EARL.HARRIS => 55 }; print join(' ', @a)."\n"; print join(' ', keys %{ $b })."\n";

Replies are listed 'Best First'.
Re: constant not evaluated
by dragonchild (Archbishop) on Sep 20, 2004 at 17:15 UTC
    use constant EARL => 'MEL';
    is (functionally) identical to the code
    sub EARL () { 'MEL' }

    The problem is that you're using it in a stringifying context - the left-hand side of the => operator. Try the following:

    my $b = { EARL() . HARRIS() => 55 };
    And see if it does what you want.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

      To depend less on how constants are implemented, just put the argument that is being stringified (before being constant-evaluated) in parentheses:
      my $b = {EARL.(HARRIS) => 55 };
      And of course, using a comma instead of the stringification operator also yields the desired result.
      my $b = {EARL.HARRIS, 55 };

      Caution: Contents may have been coded under pressure.
      Thanks for the reply. This did fix the problem.
Re: constant not evaluated
by ikegami (Patriarch) on Sep 20, 2004 at 17:18 UTC
    I didn't check, but I bet the order of precedence dictates that
    my $b = { EARL.HARRIS => 55 };
    is
    my $b = { EARL . (HARRIS => 55) };
    which is
    my $b = { EARL . ('HARRIS', 55) };
    Try
    my $b = { (EARL.HARRIS) => 55 };

    mel brooks MELBROOKS

    Update: Extra ')' removed

      ikegami, you have an extra ) after the 55.
      I removed that and it worked.

      TheEnigma

Re: constant not evaluated
by Fletch (Bishop) on Sep 20, 2004 at 18:08 UTC

    B::Deparse is your friend:

    freebie:~ 824> perl -MO=Deparse,-p,-q foo + 14:05:06 sub HARRIS () { package constant; $scalar; } sub EARL () { package constant; $scalar; } (my(@a) = map({lc($_);} 'MEL', 'BROOKS')); (my $b = {('MEL' . 'HARRIS'), 55}); print((join(' ', @a) . "\n")); print((join(' ', keys(%{$b;})) . "\n")); foo syntax OK

    (The CGI line was removed as it's not the problem here and makes a whole bunch more output.)

Re: constant not evaluated
by ysth (Canon) on Sep 20, 2004 at 19:46 UTC
    perlop says:
    The "=>" operator is a synonym for the comma, but forces any word to its left to be interpreted as a string (as of 5.001).
    It's not a matter of precedence, since . is higher precendence than , or =>. It appears that the above doc really does mean "any word to its left" rather than "its left operand" as I would have expected.

    I suspect it would be infeasible to change it to "its left operand". It may be possible to give a warning where => does force a word to be interpreted as a string but the word isn't the full left operand. I'd recommend filing a perlbug report on this.