Just another Perl shrine | |
PerlMonks |
Discover a package global's symbol name given a referenceby davido (Cardinal) |
on Sep 17, 2004 at 03:44 UTC ( [id://391652]=perlmeditation: print w/replies, xml ) | Need Help?? |
Earlier today pmneve posted the following question to Seekers of Perl Wisdom: getting the name of a variable to use as string. While ultimately the best solution to that particular question is probably a re-thinking of the script's design, it did get me thinking, and kudos to pmneve for that! ;) pmneve was asking how to discover a lexical variable's name, given...the variable. That really isn't possible in pure Perl (nor should it be necessary), as lexicals don't live in a symbol table that can be inspected from within a pure Perl script. But package globals do live in a script-accessible symbol table. The code that follows may have no practical use, and should never have been written, but I couldn't resist the challenge of walking the symbol table to find a given variable's name. The following code snippets consist of two entities. The first should be saved as SymbolName.pm. It is a package that consists of a single subroutine called get_symbol_name(). Hand this subroutine a reference of a package global (of almost any kind), and you'll get back its name as the return value. The second is a script that tests SymbolName.pm. Read on for the caveats... Now some of you are going to see a few holes here, and I think some of them are insurmountable. The first is that a reference needn't necessarily refer to a named variable. But if you pass it a reference to a package global, that issue is moot; package globals are all named. The second problem is that entities in the global symbol table may be aliased using typeglobs. That means that *foo can be aliased to *bar, meaning that $foo will be just another name for $bar. That has the effect that a given reference may be associated with more than a single symbol in the symbol table. When that happens, you have no way of being sure whether the alias or the original name will be returned. If you have aliased *foo to *bar, and you call get_symbol_name( \$foo ), you may get "foo", or you may get "bar". So sorry, them's the breaks. To use get_symbol_name(), pass it a reference to a package global, and optionally, a package name. If the package name is main, you can omit the package name and it will be assumed by default. The return value will be the symbol's name. If you pass a reference from a variable that can't be found in the symbol table, the subroutine will complain and die. It will also complain and die if you pass something other than a reference. And it will complain and die if you figure out some way of passing it a reference to a package global that isn't a SCALAR, ARRAY, HASH, GLOB or CODE. I'm posting this as a meditation because I'm interested in hearing feedback. Keep in mind, I see no practical use for this code, but do see it as an interesting topic. One issue I haven't figured out is the proper syntax for applying a *foo{THING} validity check to each option within the SWITCH block, to verify that the reference passed, and whos name was found in the symbol table, really has a valid THING. Without further pontification, here's the fiendish code. First, SymbolName.pm:
And now a little script to test it...
Comments welcomed! Dave
Back to
Meditations
|
|