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

Perhaps the following looks pathological, but I have code which needs to use hash keys which may later change in value. It made sense to utilize a layer of indirection through constants.
#!/usr/bin/perl use strict; use warnings; use constant { FOO => 'foo', BAR => 'bar' }; my %mapping = ( @{[FOO]} => 0, @{[BAR]} => 1 ); for my $k (keys %mapping) { print "$k\t$mapping{$k}\n"; }
This code appears to work given that the output is:
bar 1 foo 0
I understand that constants are implemented as subroutines which return the value assigned, but I don't understand the syntax. What is the @{[...]} syntax doing? I know that it isn't an array, and ultimately the subroutine has to be called before constructing the reference (?) into the hash, but I'm only guessing. Can you elucidate what the syntax is really specifying to the Perl interpreter?

Thanks.

Replies are listed 'Best First'.
•Re: explanation of constant syntax?
by merlyn (Sage) on Mar 20, 2004 at 02:29 UTC
    "use constant" creates a parameter-less subroutine to define the constant. Unfortunately, the quoting of a hash key bareword and the bareword quoting to the left of a fat arrow are stronger than the execution of subroutine to get its value.

    A simple workaround is to add an extra set of parens:

    my %hash = ( (FOO) => 35, (BAR) => 19, ); print $hash{(FOO)};
    There are other ways around, but I think this is the cleanest.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      I understand that the bareword FOO inside the parens is similar to when it's inside @{[...]} because it causes the subroutine created by the constant pragma to be called rather than FOO to simply be used as a hash key.

      Would you elucidate on why this happens or point me to the right perldoc to read on this subject?

      ---
      "A Jedi uses the Force for knowledge and defense, never for attack."
        Well, just break it apart:
        [ ... ]
        creates an arrayref pointing to its contents, in this case FOO (not quoted, so we get the constant value). And then:
        @{ ... }
        dereferences the enclosed value as if it were an array reference. So essentially, this is the hard way to say:
        ( ... )
        between the two of them, except that it also interpolates within a double-quoted string. That's how I stumbled across this in the first place: how to evaluate a value inside a double-quoted string. I wrote about it in a CLP posting early in the Perl5 days, and the meme stuck and is still being used in other places.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

Re: explanation of constant syntax? ()
by tye (Sage) on Mar 20, 2004 at 06:03 UTC

    I prefer using FOO() and BAR() to prevent this problem. It makes the code clearer because the function calls look like function calls.

    - tye        

      ... except people don't tend to think of constants as "function calls". That's what they are, in Perl, but it's not, er, part of their job description.

        Yep, constants aren't very clear in Perl... unless you write them like FOO(). It clears up what is really going on to the user.

        It also clears up what is going on to Perl. Barewords are quite ambiguous in Perl. Is it a function call, a string, a reserved word, a file handle, a package name, ... ? Sometimes Perl is forced to guess and sometimes guesses wrong (just like in the original node). So I almost always add the trailing parens to make things clear to man and beast.

        One exception is that I sometimes call subroutines that take arguments without the parens to get compile-time notice when I mispel the routine name. But I only do that for statements (never in the middle of an expression), because there are even more ambiguities to trip on.

        - tye