" 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
> 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/
> > 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
sounds like you need the (non-existent) Perl func uneval()
> 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
I don't think this is quite it...perhaps the Debugger's DumpPackages?
This displays the symbol tables of packages.
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]
> 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!
> 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
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 ---------
(say that I'm wrong) Did you give up on debuger?
--
Torvalds' goal for Linux is very simple: World Domination
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
> 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.
> 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