Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Get variable from its name string or vice versa?

0 views
Skip to first unread message

Jerry Krinock

unread,
May 9, 2008, 1:21:38 PM5/9/08
to
I have written a function to log variables like this:

" varName: varValue"

but it takes two arguments: the variable name as a string, and the
variable symbol:

logVar ("myVar", $myVar) ;

sub logVar {
my $varName = shift ;
my $varValue = shift ;
if (!defined($varValue)) {
$varValue = "<undef>" ;
}
printf ("%16s: %s\n", $varName, $varValue) ;
}

Is there any way to get "myVar" from $myVar or vice versa, without
foregoing 'strict' and 'warnings'?

Note: My actual code uses Std::Log but the problem is the same.

Thanks,

Jerry Krinock

A. Sinan Unur

unread,
May 9, 2008, 1:43:51 PM5/9/08
to
Jerry Krinock <je...@sheepsystems.com> wrote in news:a2761c7e-8820-4f16-
98d7-64c...@k13g2000hse.googlegroups.com:

> I have written a function to log variables like this:
>
> " varName: varValue"

This is a FAQ:

perldoc -q "How can I use a variable as a variable name"

Sinan

--
A. Sinan Unur <1u...@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/

Jens Thoms Toerring

unread,
May 9, 2008, 2:21:21 PM5/9/08
to
A. Sinan Unur <1u...@llenroc.ude.invalid> wrote:
> Jerry Krinock <je...@sheepsystems.com> wrote in news:a2761c7e-8820-4f16-
> 98d7-64c...@k13g2000hse.googlegroups.com:

> > I have written a function to log variables like this:
> >
> > " varName: varValue"

> This is a FAQ:

> perldoc -q "How can I use a variable as a variable name"

> Sinan

I think the OP is looking for something a bit different, i.e.
a way to get the name of variable from the variable itself.
I.e. some hypothetical code like

my $x = 10;
logvar( \$x );

sub logvar {
my $varref;
print get_name_from_reference( $var ) . " " . $$var . "\n";
}

It's clear that for something like this to work a reference to
the variable has to be passed to the function. But I have no
idea how to write a function like get_name_from_reference()
and also have my doubts that it is possible at all (but then
this is Perl and there's so much magic that it is hard to be
sure;-)
Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

advice please wireless 802.11 on RH8

unread,
May 9, 2008, 2:24:23 PM5/9/08
to

sounds like you need the (non-existent) Perl func uneval()

jerryk...@gmail.com

unread,
May 9, 2008, 3:38:37 PM5/9/08
to
On May 9, 11:21 am, j...@toerring.de (Jens Thoms Toerring) wrote:

> I think the OP is looking for something a bit different...

Yes, I am.

On May 9, 10:43 am, "A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:
> This is a FAQ:
>
> perldoc -q "How can I use a variable as a variable name"

I'd read that, and now studied it further, but I get the impression
that the only solution is to always define all of my variables in my
own hash, just in case I ever decided that I wanted to log one of
them.

That's not going to be any fun, and not very readable by earthlings.
Indeed, this code works:

#!/usr/bin/perl
use strict ;
use warnings ;

my %MY_VARS ;

# New Way to declare a Loggable Variable...
# Instead of just "my $fred",
# I now have to write:
my $fred = $MY_VARS{"fred"} ;

# New Way to assign a Loggable Variable
# Instead of just "$fred = 23",
# I now have to write:
$MY_VARS{"fred"} = 23 ;

# Well, after all that yuck, indeed, as desired,
# I can log it with only one argument, :

logVar("fred") ;

# Using this handy function


sub logVar {
my $varName = shift ;

my $varValue = $MY_VARS{$varName} ;


if (!defined($varValue)) {
$varValue = "<undef>" ;
}

printf ("%32s: %s\n", $varName, $varValue) ;
}

But it's hardly worth all that massive obfuscation. Can someone
confirm that there is indeed no way to simply log a "regular" variable
and its name without having to type both of them, or is Jens correct
that it can't be done?

Jerry

nolo contendere

unread,
May 9, 2008, 3:39:32 PM5/9/08
to
On May 9, 1:43 pm, "A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:
> Jerry Krinock <je...@sheepsystems.com> wrote in news:a2761c7e-8820-4f16-
> 98d7-64c1bc9ef...@k13g2000hse.googlegroups.com:

>
> > I have written a function to log variables like this:
>
> >      "         varName: varValue"
>
> This is a FAQ:
>
> perldoc -q "How can I use a variable as a variable name"
>

I don't think this is quite it...perhaps the Debugger's DumpPackages?
This displays the symbol tables of packages.

Ben Morrow

unread,
May 9, 2008, 3:37:03 PM5/9/08
to

Quoth Jerry Krinock <je...@sheepsystems.com>:

> I have written a function to log variables like this:
>
> " varName: varValue"
>
> but it takes two arguments: the variable name as a string, and the
> variable symbol:
>
> logVar ("myVar", $myVar) ;
>
> sub logVar {
> my $varName = shift ;
> my $varValue = shift ;
> if (!defined($varValue)) {
> $varValue = "<undef>" ;
> }
> printf ("%16s: %s\n", $varName, $varValue) ;
> }
>
> Is there any way to get "myVar" from $myVar or vice versa, without
> foregoing 'strict' and 'warnings'?

You can do this with PadWalker. If you need more hints than that, you
probably shouldn't be trying... :)

Ben

--
I have two words that are going to make all your troubles go away.
"Miniature". "Golf".
[b...@morrow.me.uk]

A. Sinan Unur

unread,
May 9, 2008, 5:48:54 PM5/9/08
to
jerryk...@gmail.com wrote in news:2643728c-7f39-43d9-8c46-
ca63ce...@m73g2000hsh.googlegroups.com:

> On May 9, 11:21 am, j...@toerring.de (Jens Thoms Toerring) wrote:
>
>> I think the OP is looking for something a bit different...
>
> Yes, I am.

I jumped the gun, sorry!

jerryk...@gmail.com

unread,
May 9, 2008, 8:42:19 PM5/9/08
to
On May 9, 12:37 pm, Ben Morrow <b...@morrow.me.uk> wrote:

> You can do this with PadWalker.

Thank you. I haven't tried it yet, but documentation of PadWalker
from CPAN declares a var_name() function that seems to be exactly what
I want.

Apparently this was a tricky feat. From the documentation: "I
wouldn't recommend using PadWalker directly in production code, but
it's your call. Some of the modules that use PadWalker internally are
certainly safe for and useful in production."

And from a review: "PadWalker is really, really useful if you need to
debug something really, really weird. I hope you never have to use
this module, but if you do, use it boldly."

:-|

Thanks for all the help. I'll probably give PadWalker a try next time
I am feeling bold, and have a little time to spare before production.

Jerry Krinock

Uri Guttman

unread,
May 9, 2008, 11:40:14 PM5/9/08
to
>>>>> "j" == jerrykrinock <jerryk...@gmail.com> writes:

j> On May 9, 12:37 pm, Ben Morrow <b...@morrow.me.uk> wrote:
>> You can do this with PadWalker.

j> Thank you. I haven't tried it yet, but documentation of PadWalker
j> from CPAN declares a var_name() function that seems to be exactly what
j> I want.

j> Apparently this was a tricky feat. From the documentation: "I
j> wouldn't recommend using PadWalker directly in production code, but
j> it's your call. Some of the modules that use PadWalker internally are
j> certainly safe for and useful in production."

j> And from a review: "PadWalker is really, really useful if you need to
j> debug something really, really weird. I hope you never have to use
j> this module, but if you do, use it boldly."

j> :-|

j> Thanks for all the help. I'll probably give PadWalker a try next time
j> I am feeling bold, and have a little time to spare before production.

and i doubt you have a legit reason to need this in production code. i
smell an XY problem here. when someone needs to use such a dark magic
solution, i say the problem is poorly specified or similar. tell us what
the real problem is, don't ask how to do something requiring magic. i
can find no good reason (other than debugging or wacko stuff) for
needing the name of a variable. and if you have anon references, you
can't get any name.

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------

Eric Pozharski

unread,
May 10, 2008, 4:00:00 AM5/10/08
to
jerryk...@gmail.com wrote:
*SKIP*

> Thanks for all the help. I'll probably give PadWalker a try next time
> I am feeling bold, and have a little time to spare before production.

(say that I'm wrong) Did you give up on debuger?


--
Torvalds' goal for Linux is very simple: World Domination

Peter J. Holzer

unread,
May 10, 2008, 2:31:57 PM5/10/08
to
On 2008-05-09 18:21, Jens Thoms Toerring <j...@toerring.de> wrote:
> A. Sinan Unur <1u...@llenroc.ude.invalid> wrote:
>> Jerry Krinock <je...@sheepsystems.com> wrote in news:a2761c7e-8820-4f16-
>> 98d7-64c...@k13g2000hse.googlegroups.com:
>> > I have written a function to log variables like this:
>> >
>> > " varName: varValue"
>
>> This is a FAQ:
>
>> perldoc -q "How can I use a variable as a variable name"
>
> I think the OP is looking for something a bit different, i.e.
> a way to get the name of variable from the variable itself.
> I.e. some hypothetical code like
>
> my $x = 10;
> logvar( \$x );
>
> sub logvar {
> my $varref;
> print get_name_from_reference( $var ) . " " . $$var . "\n";
> }

I think what is needed in this case a macro, not a subroutine. You want
to turn

logvar( $x );

into

print '$x' . " " . $x . "\n";

and similarly

logvar( $foo->{bar}{$y} );

into

print '$foo->{bar}{$y}' . " " . $foo->{bar}{$y} . "\n";

Macros are not part of perl per se, but can be implemented via source
filters. It shouldn't be too hard to write a filter like that.

But it happens that Damian Conway already wrote one which might do what
the OP wants: Smart::Comments.

#!/usr/local/bin/perl5.10.0
use warnings;
use strict;
use Smart::Comments;


my $var = 5;
### At <where> ...
### $var
### At <where> ...: $var
__END__

prints:

### At "./foo", line 8 ...
### $var: 5
### At "./foo", line 10 ...: 5

hp

Ben Bullock

unread,
May 10, 2008, 9:36:54 PM5/10/08
to
On Sat, 10 May 2008 20:31:57 +0200, Peter J. Holzer wrote:

> But it happens that Damian Conway already wrote one which might do what
> the OP wants: Smart::Comments.

That's very handy. I'm glad to know about it.

jerryk...@gmail.com

unread,
May 13, 2008, 10:39:17 AM5/13/08
to
On May 10, 11:31 am, "Peter J. Holzer" <hjp-usen...@hjp.at> wrote:

> I think what is needed in this case a macro, not a subroutine...


> Macros are not part of perl per se, but can be implemented via source
> filters. It shouldn't be too hard to write a filter like that.
>

Thank you, Peter. Indeed I do want a preprocessor macro, but I was
not aware that perl's preprocessor macros were called filters
(perlfilter).

> But it happens that Damian Conway already wrote one which might do what
> the OP wants: Smart::Comments.

Well, I want something which will log to the same file as Log::StdLog
does, so I wrote my own. It's got some rough edges and a kludge or
two, but it works and does not use any of the black magic. Here it
is. Thanks again for the help...

package LogVar ;

use Filter::Util::Call;

sub import {
my ($type) = @_;
my ($ref) = [];
filter_add(bless $ref);
}

sub filter {
my ($self) = @_;
my ($status);
if (($status = filter_read()) > 0) {
# Substitute for the one-argument version, LogVar(varName)
s /LogVar[\s]*\([\s]*(\$|\@|\%)([\w]+)[\s]*\)/doLogVar($2,
$1$2, info)/ ;

# Substitute for the two-argument version, LogVar(varName,
level),
# when the level is 'warn'.
# The 'warn' has to be treated specially because 'warn' is
# also a predefined function in perl and really weird things
# happen if I don't do this
s /LogVar[\s]*\([\s]*(\$|\@|\%)([\w]+),[\s]*warn[\s]*\)/
doLogVarWarn($2, $1$2)/ ;

# Substitute for the two-argument version, LogVar(varName,
level)
# for other levels
s /LogVar[\s]*\([\s]*(\$|\@|\%)([\w]+),[\s]*([\w]+)[\s]*\)/
doLogVar($2, $1$2, $3)/ ;

# Now, heres the tricky part. I need to define the functions
# doLogVar, doLogVarWarn (and makeDefined, which they call).
# For some reasons which I don't understand,
# (1) If I simply define sub doLogVar in this module, it is
# "not found" when it runs from the host program file.
# (2) If I change the calls to "LogVar::doLogVar", then it
runs,
# but nothing gets logged
# So, my workaround for these two problems is to add the
placeholder
# use logVarFunctions
# to the main program file and then replace it with the
function
# definitions using the following s///, except s''' is used
to
# avoid variable interpolations.
# This also has the advantage of using the same Log::StdLog
# initialization and thus the same level that is used in the
main
# program file.
s 'use[\s]*LogVarFunctions[\s]*;'
sub makeDefined {
my $var_ref = shift ;
if (!defined($$var_ref)) {
$$var_ref = "<undefined>" ;
}
}

sub doLogVar {


my $varName = shift ;
my $varValue = shift ;

my $level = shift ;
makeDefined(\$varValue) ;
my $msg = sprintf ("%24s: %s\n", $varName, $varValue) ;
print {*STDLOG} $level => $msg ;
}

sub doLogVarWarn {


my $varName = shift ;
my $varValue = shift ;

makeDefined(\$varValue) ;
my $msg = sprintf ("%24s: %s\n", $varName, $varValue) ;
print {*STDLOG} \'warn\' => $msg ;
}
'

}
$status;
}


1;

__END__

=head1 NAME

LogVar - Logs variable name and value using Log::StdLog

=head1 SYNOPSIS

# Your program file must be using Log::StdLog and
# have initialized it with a level.

# Both of these are necessary
use LogVar ;
use LogVarFunctions ;

my $myVar = 5 ;

# Log to Log::StdLog at default level 'info'
LogVar($myVar) ;

# Log to Log::StdLog at some other level
LogVar($myVar, trace) ;
LogVar($myVar, debug) ;
# ...
LogVar($myVar, none) ;


=head1 DESCRIPTION

This module provides a perl filter (see perlfilter), which is a
preprocessor.
It provides the macro LogVar() which extracts the variable name from
the
first argument and logs the variable name and value to the file
designated
in Log::StdLog, producing lines that are nicely aligned like this:

$myVar: 5
$name: Jerry
$weight: 150.3


0 new messages