Get variable from its name string or vice versa?

Discussion in 'Perl Misc' started by Jerry Krinock, May 9, 2008.

  1. 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
    Jerry Krinock, May 9, 2008
    #1
    1. Advertising

  2. Jerry Krinock <> wrote in news:a2761c7e-8820-4f16-
    :

    > 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 <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://www.rehabitation.com/clpmisc/
    A. Sinan Unur, May 9, 2008
    #2
    1. Advertising

  3. A. Sinan Unur <> wrote:
    > Jerry Krinock <> wrote in news:a2761c7e-8820-4f16-
    > :


    > > 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 ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, May 9, 2008
    #3
  4. On May 9, 1:21 pm, Jerry Krinock <> wrote:
    > 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


    sounds like you need the (non-existent) Perl func uneval()
    advice please wireless 802.11 on RH8, May 9, 2008
    #4
  5. Jerry Krinock

    Ben Morrow Guest

    Quoth Jerry Krinock <>:
    > 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".
    []
    Ben Morrow, May 9, 2008
    #5
  6. Jerry Krinock

    Guest

    On May 9, 11:21 am, (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" <> 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
    , May 9, 2008
    #6
  7. On May 9, 1:43 pm, "A. Sinan Unur" <> wrote:
    > Jerry Krinock <> wrote in news:a2761c7e-8820-4f16-
    > :
    >
    > > 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.
    nolo contendere, May 9, 2008
    #7
  8. wrote in news:2643728c-7f39-43d9-8c46-
    :

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

    >
    > Yes, I am.


    I jumped the gun, sorry!

    Sinan

    --
    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://www.rehabitation.com/clpmisc/
    A. Sinan Unur, May 9, 2008
    #8
  9. Jerry Krinock

    Guest

    On May 9, 12:37 pm, Ben Morrow <> 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
    , May 10, 2008
    #9
  10. Jerry Krinock

    Uri Guttman Guest

    >>>>> "j" == jerrykrinock <> writes:

    j> On May 9, 12:37 pm, Ben Morrow <> 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 ------ -------- 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 ---------
    Uri Guttman, May 10, 2008
    #10
  11. 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
    Eric Pozharski, May 10, 2008
    #11
  12. On 2008-05-09 18:21, Jens Thoms Toerring <> wrote:
    > A. Sinan Unur <> wrote:
    >> Jerry Krinock <> wrote in news:a2761c7e-8820-4f16-
    >> :
    >> > 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
    Peter J. Holzer, May 10, 2008
    #12
  13. Jerry Krinock

    Ben Bullock Guest

    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.
    Ben Bullock, May 11, 2008
    #13
  14. Jerry Krinock

    Guest

    On May 10, 11:31 am, "Peter J. Holzer" <> 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
    , May 13, 2008
    #14
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Flyingaway
    Replies:
    6
    Views:
    22,796
    Jack Klein
    Feb 19, 2005
  2. Byron
    Replies:
    6
    Views:
    499
    Byron
    Sep 16, 2004
  3. thinktwice
    Replies:
    4
    Views:
    896
    =?iso-8859-1?q?Kirit_S=E6lensminde?=
    Sep 7, 2006
  4. Astan Chee
    Replies:
    1
    Views:
    384
    Paul McGuire
    Mar 13, 2007
  5. Amit Khemka
    Replies:
    1
    Views:
    1,441
    Paul Boddie
    Mar 13, 2007
Loading...

Share This Page