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

Hi Monks,

I wonder if anyone could explain to me what is going on here...

I am looking at a module (POE::Kernel)which has the following lines of code in it :

sub MODE_RD () { 0 }  # read
sub MODE_WR () { 1 }  # write
sub MODE_EX () { 2 }  # exception/expedite

These look to me (possibly in my igorance), to be used for returning a number of constant values. The thing I don't understand, is why the empty brackets ? i.e. why aren't they written as :

sub MODE_RD { 0 }  # read
sub MODE_WR { 1 }  # write
sub MODE_EX { 2 }  # exception/expedite

There's obviously something going on here that I haven't come across before, so any care to point me in the right direction ?

Thanks very much !

Nigel.

Replies are listed 'Best First'.
Re: What are the brackets in this for ?
by Joost (Canon) on May 21, 2006 at 15:05 UTC
    The () prototype is there to enable inlining the constants, making the code a bit more efficient.

    From perlsub:

    Functions with a prototype of "()" are potential candidates for inlining. If the result after optimization and constant folding is either a constant or a lexically- scoped scalar which has no other references, then it will be used in place of function calls made without "&". Calls made using "&" are never inlined. (See constant.pm for an easy way to declare most constants.)
Re: What are the brackets in this for ?
by davidrw (Prior) on May 21, 2006 at 15:05 UTC
    The empty parens are the sub's are prototype -- see the 'Prototypes' section in perlsub. In this case they indicate that the sub is called with exactly no arguments.
Re: What are the brackets in this for ?
by gellyfish (Monsignor) on May 22, 2006 at 09:18 UTC

    As well as the potential for inlining that has already been pointed out, you also get a compile time error if you inadvertently introduce something that could be interpreted as an argument to the constant subroutine, see for instance this stupid example:

    sub FOO { 1; } + sub BAR () { 2; } + my $foo = FOO 1; + my $bar = BAR 1;
    You get the error from the BAR 1 whereas the FOO 1 is undetected, obviously in real code this could possibly be much less obvious and lead to subtle bugs.

    /J\

      Not only that, but you can leave off the parens for the prototyped sub. Otherwise you would have to write FOO() instead of FOO.

      This is usually done in situations where you would use #define in a C program to introduce a constant. In C, you would write

      #define FOO 1

      and then you could use FOO in your program and it would be the same as if you had written a literal 1. Creating a Perl sub with a prototype lets you write FOO, which looks like a constant, instead of FOO(), which looks like a sub call.

        It's not quite as cut and dried as that. The prototyping makes no difference if the subroutine is not introduced before it is first referenced, you will still get the "Bareword" error when using strict (and if you are not using strict the sub name will be taken as a string.) If you define the subroutine first or make a forward declaration (e.g sub FOO;) then you can use it without the parentheses regardless of the prototyping.

        /J\

        Not only that, but you can leave off the parens for the prototyped sub. Otherwise you would have to write FOO() instead of FOO.

        Really?

        #!/usr/bin/perl -l use strict; use warnings; sub FOO { @_? 1+shift : print 'Foo'; } FOO for 1..FOO FOO; __END__