andyford has asked for the wisdom of the Perl Monks concerning the following question:

I found out how to create variables at run time, but I don't understand how it works. I hate programming by accident, so maybe someone could enlighten me...  (eval "\$$_")->insert('end', $dat{$_})

Replies are listed 'Best First'.
Re: magic eval variables
by btrott (Parson) on May 04, 2000 at 01:28 UTC
    The expression "\$$_" is evaluated like a little Perl program and returns a value. In your case, that value seems to be a reference (an object, in fact); the insert method is then invoked on that object.

    Personally, I wouldn't really recommend doing things like this unless you're really sure what you're doing. You're basically using symbolic references, since you can also do the same thing w/o the eval. For example:

    $foo = "bar"; $_ = "foo"; print $$_;
    This prints "bar".

    A better option might be to create a hash of objects, if at all possible. But that's just my opinion.

      The rub is that I don't want to use symbolic references. I want to "use strict", and the eval thingy passes. The eval lives in a loop that extracts data from a database, and inserts into a Tk widget. The whole mess lets me explicitly name all the listboxes in the GUI, and insert into them based on the exact correspondence between the name of the column and the name of the widget.
Re: magic eval variables
by chromatic (Archbishop) on May 04, 2000 at 02:06 UTC
    To echo btrott, that's a symbolic reference which is quite confusing and easy to write incorrectly.

    As I read it, there's an object name stored in $_. It's interpolated into pseudo-existence ($) and rereferenced (\), which lets you call its insert() method. Very ugly.

    A better way to create variables at run time is by making them anonymous and storing them in some sort of data structure -- an array or a hash, for example. Novice programmers often tie themself up in loops trying to create uniquely named variables and store the names just to get at them later. Instead, learn how to use arrays and hashes and objects as containers, and save the sweating for the tricky stuff.

      i think that the "\$" is simply an escaped "$" inside double quotes, not a reference operator followed by a "$".
        Oops, you're right. Outsmarted myself. Thanks! That just goes to prove my earlier point -- this is a tricky technique, and it's easy to get lost.

        In effect, there must be a list of variable names somewhere. Let's assume a context like this:

        my @names = ("name", "rank", "serial_number"); foreach (@names) { (eval "\$$_")->insert('end', $dat{$_}); }
        For that to work, there must be objects $name, $rank, and $serial_number. As before, let Perl handle the bookkeeping:
        my %objects = ( 'name' => $name, 'rank' => $rank, 'serial' => $serial) +; foreach (@names) { $objects{$_}->insert('end', $dat{$_}); }
        Faster, more understandable, and won't muck about with your symbol table.
Re: magic eval variables
by zodiac (Beadle) on May 04, 2000 at 11:53 UTC
    this is slow because evals are slow, the argument to eval is parsed every time the eval executes. $$_ would do the same, however this will not work with use strict;unless you define a variable foreach of them using my($big $list $of $all $the $varables $you $might $want $to $use)
    the best way to do it is probably to use a hash: $objects{$_}->insert('end', $dat{$_});