Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Devel::Symdump and symbol table woes

by bpphillips (Friar)
on Nov 10, 2005 at 15:13 UTC ( [id://507395]=perlquestion: print w/replies, xml ) Need Help??

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

Hello all,
Can somone explain why the following code has the indicated output?
package private; our $my_scalar = 'my scalar'; our @my_array = qw(my array); our %my_hash = ( my => 'hash' ); package main; use strict; use Devel::Symdump; print "ARRAYS => " . join(q{, }, Devel::Symdump->arrays("private")),"\n"; print "SCALARS => " . join(q{, }, Devel::Symdump->scalars("private")),"\n"; print "HASHES => " . join(q{, }, Devel::Symdump->hashes("private")),"\n"; # yields the following __END__ ARRAYS => private::my_array SCALARS => private::my_scalar, private::my_array, private::my_hash HASHES => private::my_hash
Devel::Symdump aside, what I really want to know is why the SCALAR entry for any non-scalar symbol table glob return a reference to undef instead of simply undef:
package private; our $my_scalar = 'my scalar'; our @my_array = qw(my array); package main; use strict; use Data::Dumper; # attempt to access the ARRAY portion of a scalar *my_scalar_glob = $private::{my_scalar}; print "ARRAY portion of a scalar glob: " . Dumper(*my_scalar_glob{ARRAY}); # attempt to access the SCALAR portion of an array *my_array_glob = $private::{my_array}; print "SCALAR portion of an array glob: " . Dumper(*my_array_glob{SCALAR}); __END__ # prints the following ARRAY portion of a scalar glob: $VAR1 = undef; SCALAR portion of an array glob: $VAR1 = \undef;
Devel::Symdump checks defined-ness in determining whether a symbol of a certain type exists and since the SCALAR portion of an ARRAY symbol table entry returns \undef, it passes that test and assumes that $private::my_array really exists as a scalar.

This seems at least unexpected and possibly a flaw at some level but I'm way over my head as far as my knowledge of Perl innards.

I look forward to being enlightened!

-- Brian

Replies are listed 'Best First'.
Re: Devel::Symdump and symbol table woes
by dave_the_m (Monsignor) on Nov 10, 2005 at 15:36 UTC
    For various obscure reasons, typeglobs are always created with a Null SV in the SCALAR slot.

    Dave.

Re: Devel::Symdump and symbol table woes
by ikegami (Patriarch) on Nov 10, 2005 at 15:28 UTC

    In the past, I've noticed that entries in the symbol table (%::) always have a SCALAR component. I guess every package symbol always has a scalar component due to how Perl's guts are written.

    package main; our %test = ( a => 1 ); print('SCALAR: ', ( *{ $::{'main::'}{'test'} }{SCALAR} )?1:0, "\n"); print('ARRAY: ', ( *{ $::{'main::'}{'test'} }{ARRAY } )?1:0, "\n"); print('HASH: ', ( *{ $::{'main::'}{'test'} }{HASH } )?1:0, "\n"); ${ *{ $::{'main::'}{'test'} }{SCALAR} } = 'scalar'; print("$test\n"); __END__ SCALAR: 1 ARRAY: 0 HASH: 1 scalar
      Is this documented anywhere that you know of? Do you think this is worthy of being labeled a "bug" in Devel::Symdump (if so, I'll report it in RT)?

      Thanks for confirming I'm not going crazy anyway! :-)

      --Brian
Re: Devel::Symdump and symbol table woes
by broquaint (Abbot) on Nov 10, 2005 at 15:47 UTC
    You're seeing this behaviour because all globs slots contain references to their respective data types (as expounded upon in Of Symbol Tables and Globs). So Devel::Symdump only appears to be behaving errantly in this case, since one can't distinguish between a SCALAR slot containing nothing and a SCALAR slot which has been explicitly set to undef, such is the nature of globs :/
    HTH

    _________
    broquaint

      Just a couple of notes as a I retrace my understanding of this behavior. Here's some relevant text from perlref, section "Making References":
      *foo{THING} returns undef if that particular THING hasn’t been used yet, except in the case of scalars. *foo{SCALAR} returns a reference to an anonymous scalar if $foo hasn’t been used yet. This might change in a future release.
      One consequence of this is that at the symbol-table level, the following two packages are indistinguishable:
      { package Foo; our $x = undef; our @x = qw( alpha beta gamma ); } { package Bar; our @x = qw( alpha beta gamma ); }
      ... which I may demonstrate with some code of my own, once I come up with something convincing that navigates the sea of casting and dereferencing that is the Perl symbol table. So while I think I appreciate what broquaint is trying to get across, I don't think the above post addresses the "spirit" of the OP. I would agree with the as-yet unmade statement that Devel::Symdump is doing its best, but the underlying data is ambiguous, and so are the values returned from the module.

      Indeed, such is the nature of globs. Thanks, bpphillips, for starting this conversation.

      Update: Here's a more concrete example, following the package definitions above:

Re: Devel::Symdump and symbol table woes
by planetscape (Chancellor) on Nov 10, 2005 at 16:19 UTC

    Depending, of course, on what you ultimately want to do with this, you might want to look at Dumpvalue, which can dump the symbol tables of whole packages, or at another of the modules listed here.

    For example,

    package private; our $my_scalar = 'my scalar'; our @my_array = qw(my array); our %my_hash = ( my => 'hash' ); package main; use strict; use Devel::Symdump; use Dumpvalue; print "ARRAYS => " . join(q{, }, Devel::Symdump->arrays("private")),"\n"; print "SCALARS => " . join(q{, }, Devel::Symdump->scalars("private")),"\n"; print "HASHES => " . join(q{, }, Devel::Symdump->hashes("private")),"\n"; print "\nDumpvalue:\n"; Dumpvalue->new->dumpvars('private');

    yields this output:

    ARRAYS => private::my_array SCALARS => private::my_scalar, private::my_array, private::my_hash HASHES => private::my_hash Dumpvalue: @my_array = ( 0 'my' 1 'array' ) $my_scalar = 'my scalar' %my_hash = ( 'my' => 'hash' )

    which lends itself to visual inspection.

    Update: Added example.

    HTH,

    planetscape

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://507395]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-04-25 20:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found