symbol table question

R

Richard Trahan

Consider the following code:

package mypackage;
$x = 7;
otherpackage::mysub($x);
....
package otherpackage;
sub mysub
{
# retrieve variable name here
}

In mysub, I would like to retrieve the name mypackage::x, as well as
the variable type (SCALAR). How do I do that? I know how to use
caller() to retrieve the caller's package, and I know how to iterate
through the caller's symbol table to retrieve symbolic names
and existence of types, but I don't know how to associate one
of them with the alias to $x in mysub, i.e., $_[0].

Any help, please. Thanks.
 
B

Brian McCauley

Richard said:
Consider the following code:

package mypackage;
$x = 7;
otherpackage::mysub($x);
...
package otherpackage;
sub mysub
{
# retrieve variable name here
}

In mysub, I would like to retrieve the name mypackage::x, as well as
the variable type (SCALAR). How do I do that? I know how to use
caller() to retrieve the caller's package, and I know how to iterate
through the caller's symbol table to retrieve symbolic names
and existence of types, but I don't know how to associate one
of them with the alias to $x in mysub, i.e., $_[0].


if ( \${"${caller}::$name"} == \$_[0] ) {
print "First argument to mysub is \$$name in package $caller\n";
}
Any help, please.

More helpfull would be the advice "Don't do this". Package variables
are very rare in modern well written Perl code, most variables are
lexicially scoped so won't have a name in the symbol table. Some, of
course, could have more than one.

What are you trying to achive? This smells distictly X-Y.

If your subroutine really must take an argument that is a symbol table
entry (which I think is unlikely) then it is better to make it
explicitly do so. Actually I hate psudo-GLOBs so I'd pass a GLOBref.

$x = 7;
otherpackage::mysub(\*x);
 
R

Richard Trahan

Brian said:
What are you trying to achive? This smells distictly X-Y.
Thank you for your response. I hadn't thought of equating the references.

I am expanding the Track program in Damian Conway's book, chapter on
Ties. The procedure, for scalars, is to call a tracking class which ties
the tracked variable after setting up a hash object and some stuff in
the STORE and FETCH methods which record caller() info. The proc is
limited in that it does not print the variable names, and it's
cumbersome to look at source code to match caller() info to debug
output in order to determine what variable is being dumped.

Another limitation is that the Track class, as shown in Conway's
book, relies on sub aliasing of @_ to variables, provided they're
scalars. For example, the setup for tracking a scalar is:
Track->scalar($myvariable)
In Track::scalar(), $_[0] is the class name ("Track") and $_[1] is
aliased to $myvariable (I've never been quite sure what an alias
is under the hood, although I know it refers to the same memory
location). But if you try to do something like:
Track->hash(%myhash)
it doesn't work, since Perl flattens %myhash into a list, rather than
putting an alias into $_[1]. If you try something like
Track->hash(\%myhash), you get a reference in hash(), and I don't know
how to tie a variable if you only have a reference to it. (I think
dereferencing it produces a copy of the hash, not an alias.) Therefore,
the Track class cannot be expanded to include hashes using this procedure.

Instead, the program setting up the tracking must call
tie(%hash,"Track",@arglist); tie() seems to be a magic syntax that
doesn't flatten %hash. (This is not explained anywhere, AFAIK.)

I don't like symbol tables either, thank you, but I think they're
necessary when developing debuggers and IDEs.

BTW, if you're into Tk, could you have a look at my other post? That's a
more serious problem for me now, and I've had trouble finding Tk fellow
travelers.
 
R

Richard Trahan

Jim said:
Have you looked at comp.lang.perl.tk ? I think they are hanging out
there.
Thank you. I would have found this before Google screwed up their Groups
by removing computer/programming/languages; now it doesn't show up
anywhere, but I found it in my browser subscriptions list.
 
B

Brian McCauley

Richard said:
Thank you for your response. I hadn't thought of equating the references.

I am expanding the Track program in Damian Conway's book, chapter on
Ties. The procedure, for scalars, is to call a tracking class which ties
the tracked variable after setting up a hash object and some stuff in
the STORE and FETCH methods which record caller() info. The proc is
limited in that it does not print the variable names,

Not all variables have names you know.
and it's
cumbersome to look at source code to match caller() info to debug
output in order to determine what variable is being dumped.

Then extend the API to allow you to pass a descriptive string along with
the variable.
Another limitation is that the Track class, as shown in Conway's
book, relies on sub aliasing of @_ to variables, provided they're
scalars. For example, the setup for tracking a scalar is:
Track->scalar($myvariable)
In Track::scalar(), $_[0] is the class name ("Track") and $_[1] is
aliased to $myvariable (I've never been quite sure what an alias
is under the hood, although I know it refers to the same memory
location).
But if you try to do something like:
Track->hash(%myhash)
it doesn't work, since Perl flattens %myhash into a list, rather than
putting an alias into $_[1]. If you try something like
Track->hash(\%myhash), you get a reference in hash(), and I don't know
how to tie a variable if you only have a reference to it. (I think
dereferencing it produces a copy of the hash, not an alias.)

I suggest you stop thinking that because it is wrong. Once you stop
thinking it your other problem goes away.
Instead, the program setting up the tracking must call
tie(%hash,"Track",@arglist); tie() seems to be a magic syntax that
doesn't flatten %hash. (This is not explained anywhere, AFAIK.)

Perl's builtin functions are able have magic syntax that a user-defined
Perl function could not emulate. Some may even have syntax that not
even a user defined XS function could emulate. tie() one of these. You
can tell this because prototype('CORE::tie') is undef.

You can go some way towards the magic syntax using a prototype.
Prototypes are explained in perlsub. But because prototypes are
implemented as compile-time syntactic sugar and method calls are
resolved at runtime, a subroutine called as a method ignores its prototype.
I don't like symbol tables either, thank you, but I think they're
necessary when developing debuggers and IDEs.

There are two types of symbol table in Perl the first are internally
called stashes and externally know as packages or namespaces. The other
type of symbol table is known as a pad. If one says unqualified "symbol
table" one is assumed to mean stash.

In a typical (well written) Perl program the vast majority of variables
are lexically scoped and reside in pads. The next most prevelant
variables are anonymous ones that have no entry in either a stash or a
pad. And finally a tiny minority of variables exist in stashes.

I'm ignoring here special variables as documented in perlvar - these too
reside in stashes but you are unlikely to want to Track them and quite
often they can't be tied.

If you are writing debugging tools then you can manipulate pads using
PadWalker but in this case I would not recommend it - just pass the name
as another argument.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top