On May 17, Paul Johnson said:

>You can't.  You are trying to use symbolic references and when you have
>strict turned on you are promising not to do that.

>my $varname = "myvar";
>{
>    no strict "refs";
>    no strict "vars";
>    @$varname = ('a','b','c');
>}

It's important to know one thing:

  SYMBOLIC REFERENCES are means of getting to package variables!

As shown by this demonstration:

  my $foo = "bar";
  $main::foo = "BAR";

  my $name = "foo";
  print $$name;  # prints 'BAR'

Now, as we all know (chances are a lot of us don't know), package
variables are different from my() variables because package variables
exist in something called the "symbol table".  This is a hash, pretty much
like any other hash, that Perl uses to keep track of variables in every
package.

  package Example;

  $foo = 2;
  @bar = (5,3,1);
  %blat = (hello => 'world');
  sub blat { print "hey HEY!" }

  for my $symbol (sort keys %Example::) {
    print "  \$$symbol defined\n" if defined $$symbol;
    print "  \@$symbol defined\n" if defined @$symbol;
    print "  \%$symbol defined\n" if defined %$symbol;
    print "  \&$symbol defined\n" if defined &$symbol;
  }

That tells me:

  @bar defined
  %blat defined
  &blat defined
  $foo defined

Pretty nifty, eh?  But this doesn't run under 'strict refs', since $symbol
is a string (they're just keys in a hash, and keys in hashes are simple
strings).  So how can we get this to work under strict, without turning it
off for our evil purposes?

By *using* the symbol table.  Not just looking at it, but extracting
content from it.

Watch:

  package Example;

  $foo = 2;
  @bar = (5,3,1);
  %blat = (hello => 'world');
  sub blat { print "hey HEY!" }

  use strict;

  for my $symbol (sort keys %Example::) {
    print "  \$$symbol defined\n" if defined ${ $Example::{$symbol} };
    print "  \@$symbol defined\n" if defined @{ $Example::{$symbol} };
    print "  \%$symbol defined\n" if defined %{ $Example::{$symbol} };
    print "  \&$symbol defined\n" if defined &{ $Example::{$symbol} };
  }

First, you'll notice I waited to 'use strict' until after the variable
declarations.  I could have done 'use vars qw( $foo @bar %blat )', but I
decided to be lazy.

Second, you'll notice we've replaced John's regular coffee grounds with
Folgers Decaffeinated.  Let's see if he notices.

D'oh.

Second, you'll notice the defined($$symbol) is now something that looks a
bit hairier. :(  Don't worry.  Like I said, %Example:: is just a
hash.  But it's the values of this hash that are magical.

The values of this hash are typeglobs.  A typeglob is a variable, *foo,
that holds references to $foo, @foo, %foo, and &foo (and a bit more).

You can treat a typeglob as ANY sort of reference!  So...

  - if $SymbolTable::{$name} returns a typeglob...
  - and a typeglob can be dereferenced to anything...
  - then ${ $SymbolTable::{$name} } is like...
  - $SymbolTable::name

So we've just gotten at a variable in a package, by KNOWING ITS NAME, and
getting it from the symbol table, and it's all strict compliant.

It's also very rare you'd ever have to do this.  But I like to think it's
better to know some things about Perl even if you never use them.

-- 
Jeff "japhy" Pinyan      [EMAIL PROTECTED]      http://www.pobox.com/~japhy/
Are you a Monk?  http://www.perlmonks.com/     http://forums.perlguru.com/
Perl Programmer at RiskMetrics Group, Inc.     http://www.riskmetrics.com/
Acacia Fraternity, Rensselaer Chapter.         Brother #734
*** I need a publisher for my book "Learning Perl Regular Expressions" ***

Reply via email to