tags:

views:

145

answers:

2

Possible Duplicates:
Perl sub to print out a variable and its value
How to get name of object in perl

I'm trying to create a sub called "debug" in an existing Perl script (which runs as a CGI under Apache2) and I want to call it from any other sub in the script and pass it the name of a local variable in that sub in order to inspect (and print out) the variable's current value.

For example:

sub somesub {
  my $examplevar = 'abc';
  debug('examplevar');
  # or debug($examplevar); ??
}

The output in this case should be:

$examplevar: abc

I'm trying to avoid doing something like:

debug('examplevar', $examplevar);

because that's (and I'm hoping, unnecessary) extra typing.

The script has "use strict;" set and I've read "perldoc -q 'variable as a variable name'". Is there any way to achieve this without using symbolic references, while still only passing one parameter to the debug sub?

+11  A: 

I think you are looking for PadWalker:

#!/usr/bin/perl

use strict; use warnings;

use Carp;
use PadWalker qw( peek_my );
use YAML;

my $x = 5;
my %h = ( a => 1, b => 2);

debug('$x', '%h', '@z');

sub debug {
    my $pad = peek_my(1);

    for my $var ( @_ ) {
        if ( exists $pad->{$var} ) {
            printf "%s =\n%s\n", $var, Dump($pad->{$var});
        }
        else {
            carp "Cannot locate variable '$var'";
        }
    }
    return;
}
Sinan Ünür
Probably a bit too complicated for what I was trying to do and (as a beginner) a bit too advanced for me as well. I'll have a look anyway, though. Thank you! :)
RCH
A: 

Edit: fixed code, thanks to Eric Strom and Michael Carman for comments.

You can write a simple wrapper. For example:

sub debugvar
{
   my $name = shift;
   my $value = eval "return \$" . $name;
   debug ("$name = $value");
} 

....

$examplevar = 'abc';
debugvar('examplevar');
# outputs: $examplevar = abc

Also I recommend you take a look at Data::Dumper.

Note: this should work only for global variables, i.e. if you are using short scripts. For big scripts, please, use Sinan's solution with PadWalker.

omlin
Perfectly simple and effective enough for what I was looking to do - thank you! I was actually pretty close to just that, but couldn't get the eval idea working. I tried: eval "print '$' . $name" (and other weird variations) and eventually ended up knee-deep in documentation about symbolic refs ($$var, ${$var}) etc. :P
RCH
This only works for global variables and lexical (my) variables visible to the definition of the sub.
Michael Carman
Exactly. But this is enough for short scripts and this is very simple to understand. I suppose, RCH wanted simple and independent solution, without using modules. Look, we are answering the questions here, concrete questions, and we can recommend not to use the solution, but we might not force. Anyway, I mentioned the Data::Dumper, it is a great module without any limitations, and actually, I don't understand this downvote...
omlin
-1, here's your explanation: first off, the `()` in `sub debugvar()` is an error which makes your example code throw an error (since debugvar is prototyped to take no arguments). Secondly, your `my $examplevar` needs to be defined before the definition of `debugvar` for it to work. Third, your solution only works for scalar variables. So your example code does not even work, and the solution itself is of highly questionable quality. Take a look at Sinan's answer (or the answer I linked to in a comment to the OP) for the correct way to solve this problem.
Eric Strom
Thank you for the explanation. You're right, it does not work, but RCH got the idea, isn't that enough? Also, he told in the question what he have read http://faq.perl.org/perlfaq7.html#How_can_I_use_a_vari - so, I think, he understands variable visibility. Your and Sinan's solutions are great, but they are a bit complicated, and, for example, my hosting provider does not have PadWalker.
omlin
And, just for reference, do you have same solution without PadWalker?
omlin
The point is, if you can't install PadWalker, then the only correct solution involves passing both the name and the variable to the debugvar routine. We wouldn't have added it as a requirement if it wasn't necessary. Also, your answer does not fit with the OP's requirements: `Is there any way to achieve this without using symbolic references`. `eval`'s caveats are a proper superset of the caveats of symbolic references.
Eric Strom
Thank you for your explanations, and sorry if my answer cut to the heart... Really, I will try answer better next time.
omlin