$ref = \%hash;
$ref = \@hash;
How do I do the same thing as reference using typeglob in perl?
What's the exact steps perl takes to interpret $$ref{key}
?
If you're asking how you get a reference to a type glob, it's just:
my $ref = \*symbol_name_here;
For a "literal name" of the symbol, (that is where you type in the exact name of the symbol), and not a variable. But, you can do this:
my $ref = Symbol::qualify_to_ref( $symbol_name );
for a variable symbol. However, the above works with strict
and the easier one below doesn't:
my $ref = \*{$symbol_name};
One of the nice things about Symbol::qualify*
, is that it handles package names as the second variable. So...
my $sref = Symbol::qualify_to_ref( $symbol_name, $some_other_package );
does the same thing as \*{$some_other_package.'::'.$symbol_name}
and it works with strict
.
Once you have the symbol ref, to get the slot, you have to deference the reference, so perl does not think you're trying to use it as a hash, like so.
my $href = *{ $sref }{HASH};
my $code = *{ $sref }{CODE};
my $arref = *{ $sref }{ARRAY};
my $io = *{ $sref }{IO};
I put your two ideas together in a different way. If you have a symbol table reference, you can get the HASH
slot and that is a reference just like any other reference to a hash. So you can do the following.
Either
*hash{HASH}->{key}
Or
${ *hash{HASH} }{key}
will work. These are safer, though
( *hash{HASH} || {} )->{key};
${ *hash{HASH} || {} }{key};
If you want to do this not with a direct entry, but a reference into the table, you would do the following:
my $ref = \*hash;
my $value = *{ $ref }{HASH} && *{ $ref }{HASH}->{key};
NOTE: %hash
absolutely needs to be a package variable. Only package variables reside in the symbol table (so only subs and @ISA
and Exporter variables tend to be in modern symbol tables). Lexical variables (those declared my
) reside in the "pad".
UPDATE:
I have gotten away from using Symbol
so much. Curiously, even though it is core, it seems non-standard in the way Perlers do--and see--things. Instead, I use the direct way in what I call "no-blocks", as localized as I can make them.
# All I want is one symbol.
# Turn strict-refs off, get it, turn it back on.
my $symb = do { no strict 'refs'; \*{$symbol_name} };
OR
{ no strict 'refs';
*{$package_name.'::'.$symbol_name} = $sub_I_created;
... # more reckless symbol table mucking...
}
I almost always use the *STDERR{IO}
idiom for a glob file handle reference. In modern Perl, these are usually objects.
my $fh = *STDERR{IO};
say blessed( $fh ); # IO::File
$fh->say( 'Some stuff' );