in reply to Re: %hash (@array && use constant) in Modules
in thread %hash (@array && use constant) in Modules

Array versus hash isn't an issue if you ask me. The penalty you pay for constants is probably larger than those for a hash lookup. Constants are really subroutines, and subroutine calls use the stack.
Constant subs get (or at least should get) their values inlined at compile time. No runtime penalty there.
  • Comment on Re: Re: %hash (@array && use constant) in Modules

Replies are listed 'Best First'.
Re^3: %hash (@array && use constant) in Modules
by tadman (Prior) on Apr 23, 2002 at 22:10 UTC
    "Should get" versus "do get" is an important distinction. Have a look inside constant and see:
    { no strict 'refs'; my $full_name = "${pkg}::$name"; $declared{$full_name}++; if (@_ == 1) { my $scalar = $_[0]; *$full_name = sub () { $scalar }; } elsif (@_) { my @list = @_; *$full_name = sub () { @list }; } else { *$full_name = sub () { }; } }
    Looks like a regular subroutine for me. No inline. Maybe in Perl 6.
      Incorrect. If it looks like a regular subroutine to you that only means you don't know what an inlined subroutine looks like! I suggest you spend some time with Benchmark and prove to yourself that "use constant" really does result in inlined subroutines.

      -sam

        Time well spent. Thanks for the insight, samtregar, and Elian. Two letters, '()', can make a whole lot of difference. Wow.

        I've been trying to kill off references to Tie::Const, a deprecated module from ages ago, and now I think this might just do the trick.
      Benchmarking tells you if something is faster or not. B::Deparse tells you how Perl compiled your code. Both are useful in a case like this, so here's the Deparse way...
      <mir 112 [8:56] ~ >perl -MO=Deparse -le 'use constant X=>17; print X' -e syntax OK sub X () { package constant; $scalar; } print 17;

      When the person above you said 'inline', I don't think he was referring to Inline::C or anything like that. Rather, that the Perl compiler knows to optimize "constant" subroutines at compile-time and replace its subroutine/stack-calling stuff with... well, constant values

      As an example, I created a program around the "Foo" package example we're using here, and I expanded the "Foo" package as well. Here it is:

      #!/usr/bin/perl -w
      
      use strict;
      
      my $foo = Foo->new();
      
      $foo->setBar('10');
      
      print "\$foo's 'bar' value is = " . $foo->getBar() . "\n";
      
      exit 0;
      
      package Foo;
      
      use constant BAR      => 1;
      use constant BAZ      => 2;
      use constant SO_ON    => 3;
      use constant SO_FORTH => 4;
      
      sub new {
          return bless ([], +shift);
      }
      
      sub getBar {
          my $self = shift;
          $self->BAR;
      }
      
      sub setBar {
          my $self = shift;
          $self->BAR = +shift;
      }
      

      Now, look at what this looks like when I run it through B::Deparse

      rdice@tanru:~$ perl -MO=Deparse,-uFoo constants.pl
      my $foo = 'Foo'->new;
      $foo->setBar('10');
      print q($foo's 'bar' value is = ) . $foo->getBar . "\n";
      exit 0;
      sub Foo::BAR () {
          package constant;
          $scalar;
      }
      sub Foo::BAZ () {
          package constant;
          $scalar;
      }
      sub Foo::SO_ON () {
          package constant;
          $scalar;
      }
      sub Foo::SO_FORTH () {
          package constant;
          $scalar;
      }
      sub Foo::new {
          package Foo;
          return bless([], shift @_);
      }
      sub Foo::getBar {
          package Foo;
          my $self = shift @_;
          $$self1;
      }
      sub Foo::setBar {
          package Foo;
          my $self = shift @_;
          $$self1 = shift @_;
      }
      constants.pl syntax OK
      

      This is a reflection of how Perl sees this program after compilation and optimization. Notice that there is NO subroutine call within sub Foo::getBar or sub Foo::setBar with regards to the BAR 'constant', which is really a subroutine, but has been optimized back to being a constant -- namely, "1".

      Cheers,
      Richard