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

After much searching, I can not discover the *meaning* of the leading ampersand ("&") in package constants such as shown in the following example:
sysopen (ioport, $portname, &POSIX::O_RDWR);
Any pointers to narrow my search would be most appreciated - thanks, Scott.

Replies are listed 'Best First'.
Re: Ampersand prefix for package constants ?
by jonadab (Parson) on Sep 30, 2003 at 19:23 UTC

    The & is the sigil for code. &foo is for subroutines what $foo is for scalars and @foo is for arrays and so on. &POSIX::O_RDWR is probably defined in package POSIX as a sub O_RDWR { ... }

    In Perl5, the & does not necessarily take a reference to the subroutine; it could be calling the routine, depending on several things. In Perl6 this will get cleared up, and the & sigil will always take a coderef.


    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
Re: Ampersand prefix for package constants ?
by liz (Monsignor) on Sep 30, 2003 at 20:17 UTC
    In Perl 5, constants _are_ subroutines:

    use constant FOO => 42;
    is basically syntactic sugar for:
    sub FOO { 42 }

    Normally, you wouldn't need to use the & sigil, but many of the POSIX constants are basically AUTOLOADed subroutines. So I bet you have something like:

    use POSIX ();
    at the start of your program. Because the subroutines have not been encountered at compile time, the compiler needs a hint that it is a subroutine (otherwise it will assume it is a "bareword"). Observe:
    $ perl -mPOSIX -e '$a = POSIX::O_RDWR; print "$a\n"' POSIX::O_RDWR $ perl -mPOSIX -e '$a = &POSIX::O_RDWR; print "$a\n"' 2

    An alternate way is to export the constant your own namespace so that you can refer to it directly without the POSIX:: prefix:

    use POSIX qw(O_RDWR);
    or, as a one liner:
    $ perl -mPOSIX=O_RDWR -e '$a = O_RDWR; print "$a\n"' 2

    Hope this helps.

    Liz

Re: Ampersand prefix for package constants ? (don't)
by tye (Sage) on Sep 30, 2003 at 21:57 UTC

    Calling subroutines with an ampersand but without parentheses is a special invocations that preserves @_ and should only be used in special advanced situations. This is not one of those.

    You'd be better off writing POSIX::O_RDWR() or (if you used strict) POSIX::O_RDWR. Some information related to such choices is summarized in (tye)Re: A question of style.

    Update: For those players at home confused by this answer (thinking I got my advice backward as far as strict.pm is concerned, one of whom was kind enough to /tell me about it)... The point of strict.pm is pretty much to catch simple mistakes, including typos.

    Let's take two simple mistakes as examples: 1) you mispelt "O_RDWR" or 2) forgot to "use POSIX". Now consider these correct usages:

    perl -le " use POSIX; print 'x',POSIX::O_RDWR();" perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWR();" perl -le " use POSIX; print 'x',POSIX::O_RDWR;" perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWR;"
    which gives us results similar to the following:
    > perl -le " use POSIX; print 'x',POSIX::O_RDWR();" x2 > perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWR();" x2 > perl -le " use POSIX; print 'x',POSIX::O_RDWR;" x2 > perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWR;" x2
    Now consider these mistakes:
    perl -le " print 'x',POSIX::O_RDWR();" perl -le " use POSIX; print 'x',POSIX::O_RDWT();" perl -le "use strict; print 'x',POSIX::O_RDWR();" perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWT();" perl -le "use strict; print 'x',POSIX::O_RDWR;" perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWT;"
    which are all caught for us as follows:
    > perl -le " print 'x',POSIX::O_RDWR();" Undefined subroutine &POSIX::O_RDWR called at -e line 1. > perl -le " use POSIX; print 'x',POSIX::O_RDWT();" O_RDWT is not a valid POSIX macro at -e line 1 > perl -le "use strict; print 'x',POSIX::O_RDWR();" Undefined subroutine &POSIX::O_RDWR called at -e line 1. > perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWT();" O_RDWT is not a valid POSIX macro at -e line 1 > perl -le "use strict; print 'x',POSIX::O_RDWR;" Bareword "POSIX::O_RDWR" not allowed while "strict subs" in use at -e +line 1. Execution of -e aborted due to compilation errors. > perl -le "use strict; use POSIX; print 'x',POSIX::O_RDWT;" Bareword "POSIX::O_RDWT" not allowed while "strict subs" in use at -e +line 1. Execution of -e aborted due to compilation errors.
    and finally consider these mistakes:
    perl -le " print 'x',POSIX::O_RDWR;" perl -le " use POSIX; print 'x',POSIX::O_RDWT;"
    which are not caught for us:
    > perl -le " print 'x',POSIX::O_RDWR;" xPOSIX::O_RDWR > perl -le " use POSIX; print 'x',POSIX::O_RDWT;" xPOSIX::O_RDWT
    and you see why I say you should only write POSIX::O_RDWR if you used strict (because if you try to write POSIX::O_RDWR without using strict.pm, you aren't protected from a simple mistake going unreported).

                    - tye