SPUG: Using subroutines to return constants

Brian Ingerson briani at activestate.com
Sat Nov 4 14:38:55 CST 2000


Richard Anderson wrote:
> 
> Subtitle: Structured coding best practice or performance-crippling hack?
> 
> Although Perl 5.6 has the convenient constant declaration to fix the value

"use constant" preceeds 5.6. I assume that was the convenience that you
meant.

> of a variable, most of us are still coding without this bit of syntactic
> sugar.  The traditional way to refer to a constant in Perl is to use a
> reference to a subroutine that does nothing but return the constant:
> 
> $PI = sub { 3.1415962 };

Not the tradition I'm familiar with. I think the traditional idiom is:

sub PI { 3.1415926 }

Then you can say:

my $area = PI * $r ** 2;

Your way, you'd say:

my $area = &$PI $r ** 2;

You might as well just defined it as:

my $PI = 3.1415926;

> 
> I get a performance slowdown factor of 7 for the subroutine call on both
> Windows and Linux.  Pretty nasty hit just to make your code cleaner.
> 
> Any thoughts on this?

Yes. Perl will "inline" any sub that is prototyped and evaluates to a
constant. So using this:

sub PI () { 3.1415926 }

will effectively replace all references to PI with the constant. "use
constant" does the same thing. A good explanation of this is in the new
Camel p228.

Running this:

----------------8<----------------------------
my $PI_1 = sub { 3.1415962 };
sub PI_2 { 3.1415962 };
sub PI_3 () { 3.1415962 };
use constant PI_4 => 3.1415962;
my $PI_5 = 3.1415962;

use Benchmark;
my $r = 7;
timethese(10_000_000,
          {
           subref   => sub {&$PI_1 * $r ** 2},
           sub      => sub { &PI_2 * $r ** 2},
           inline   => sub {  PI_3 * $r ** 2},
           constant => sub {  PI_4 * $r ** 2},
           scalar   => sub { $PI_5 * $r ** 2},
          }
         );
----------------8<----------------------------

produces:

Benchmark: timing 10000000 iterations of constant, inline, scalar, sub,
subref...
  constant: 13 wallclock secs (13.88 usr +  0.00 sys = 13.88 CPU)
    inline: 14 wallclock secs (13.73 usr +  0.02 sys = 13.75 CPU)
    scalar: 14 wallclock secs (13.58 usr +  0.00 sys = 13.58 CPU)
       sub: 25 wallclock secs (24.37 usr +  0.00 sys = 24.37 CPU)
    subref: 25 wallclock secs (24.76 usr +  0.00 sys = 24.76 CPU)



Just say "use constant"

Brian

-- 
perl -e 'use Inline C=>q{SV*JAxH(char*x){return newSVpvf
("Just Another %s Hacker\\n",x);}};print JAxH+Perl'

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     POST TO: spug-list at pm.org       PROBLEMS: owner-spug-list at pm.org
      Subscriptions; Email to majordomo at pm.org:  ACTION  LIST  EMAIL
  Replace ACTION by subscribe or unsubscribe, EMAIL by your Email-address
 For daily traffic, use spug-list for LIST ;  for weekly, spug-list-digest
  Seattle Perl Users Group (SPUG) Home Page: http://www.halcyon.com/spug/





More information about the spug-list mailing list