Look at the following snippet of code (do not run it yet).

#!/usr/bin/perl -w use strict; use constant BAR => 3; use constant FOO => 2, BAZ => 1, JAPH => 0; print BAZ,$/;

What happens?

If you said that it outputs the value 1, then you would be wrong. Why? No comma allowed after filehandle at constant.pl line 5. Say what? That's right. There is no constant named BAZ so Perl reads it as a filehandle.

Replace print BAZ,$/; with print +(FOO)[BAR],$/;. Now what happens?

If you said outputs the string "JAPH", then you would be right. Why? use constant FOO => 2, BAZ => 1, JAPH => 0; creates a constant named FOO containing the array list (2, 'BAZ', 1, 'JAPH', 0). Don't believe me? See what happens when you add this to the end of the script:
foreach (FOO) { print $_,$/; }

None of this should be a surprise to any one who is familiar with the constant pragma. Normally constants must be declared one per statement. You may also "define multiple constants in a single statement by giving, instead of the constant name, a reference to a hash where the keys are the names of the constants to be defined. Obviously, all constants defined using this method must have a single value."

use constant { FOO => 3, BAR => 2, BAR => 1, JAPH => 0, };
So if you need a constant to contain an array or a hash, it must have it's own declaration statement.

Updated: I posted this in the hope that it may shed some additional light on the subject. Thank you PodMaster.

Replies are listed 'Best First'.
Re: constant confusion
by PodMaster (Abbot) on Apr 23, 2003 at 14:55 UTC
    That's how it works.
    perl -l -- use constant FOY => 1, 2, 3, 4; print for FOY; __END__ 1 2 3 4
    the constant pod gives use constant USERINFO       => getpwuid($<); as an example, and then further goes to show
    List constants are returned as lists, not as arrays. $homedir = USERINFO[7]; # WRONG $homedir = (USERINFO)[7]; # Right
    The pod says
    
    DESCRIPTION
        This will declare a symbol to be a constant with the given scalar or
        list value.
    
    Seems pretty clear to me.


    MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
    I run a Win32 PPM repository for perl 5.6x+5.8x. I take requests.
    ** The Third rule of perl club is a statement of fact: pod is sexy.

Re: constant confusion
by perrin (Chancellor) on Apr 23, 2003 at 15:31 UTC
    Note that it would be far less confusing to simply use globals:
    use vars qw($FOO $BAR $BAZ $JAPH); $BAR = 3; ($FOO, $BAZ, $JAPH) = (3, 2, 1);
    Even a Perl toddler who doesn't appreciate the finer points of the constant pragma can read that.
Re: constant confusion
by crenz (Priest) on Apr 23, 2003 at 16:19 UTC

    Thanks for bringing that to our attention. However, I don't use constant anyway. I don't like the "filehandle-ish" look of the constants; I find it more perlish to just use normal variables, but with uppercase names. Yes, this way they can be modified, but everybody should know they shouldn't :).

      Constants must start with a letter (or underscore) but there is nothing that says that they must be uppercase.

      "The use of all caps for constant names is merely a convention, although it is recommended in order to make constants stand out and to help avoid collisions with other barewords, keywords, and subroutine names. Constant names must begin with a letter or underscore. Names beginning with a double underscore are reserved. Some poor choices for names will generate warnings, if warnings are enabled at compile time."
        Yeah, but that statement is a bit silly. Using all cap names doesn't avoid collision with other barewords. Typical barewords found in Perl programs are uppercase: file and directory handles. The other major category of barewords are in titlecase: package names. Barewords as in unquoted strings I only find in the student books of the Perl courses of HP Education.

        Avoiding collisions with subroutine names? Come again? You know which subroutine names you are using, don't you? Besides, what if you do use subroutines, aren't you in grave danger of colliding with other subroutine names? No, of course not. It's not a problem for the set of subroutines in a program, and won't suddenly be a problem if you use lowercase constants.

        Leaves us collisions with keywords. Well, you know which keywords there are, so it's easy to avoid them. The only potential problem you have is when you upgrade perl, new keywords might be introduced. Of course, you already have a problem because subroutine names can collide as well. But how common are new keywords in new versions of Perl anyway? In the last couple of yours, new keywords are our and lock, both introduced in 5.005. But in 5.005, we also saw the birth of INIT and in 5.6.0, CHECK was introduced. So, using all caps is as likely to cause a collision as to use all lowercase.

        If you want to reduce the chance of collisions, you'd use names starting with a lowercase letter, and having one or more uppercase letters in them as well.

        Abigail

        Yes, but I find constants even weirder when just using lowercase. I find it easier to maintain code if I stick to the usual sigils, uppercase FILEHANDLEs and lowercase sub_names. Using constant would somewhat spoil that scheme. Or maybe I'm just not flexible enough :)

      All my file handles these days are lexicals, as they should be. That means all-uppercase identifiers are free for the taking, and constant gets them.

      Makeshifts last the longest.