[comp.lang.perl] using contents of a scalar variable as a variable name

knodel@news.colorado.edu (KNODEL DAVID) (04/12/91)

In a perl application I am writing, I would find it extremely useful
to reference variables whose names are stored in an array.  The only
way which consistently worked was to use an eval statement.  For example,
if I have an array:

@names=("john","joe","paul");

and I want to assign values to the variables whose names appear
in the array (in this case, $john, $joe, and $paul).  I found that
I could reference them via an eval statement, like:
print eval("\$$names[0]");

but assigning to them via this method was a little gross:

eval("\$$names[0] = \"something\");

Is there a better way to reference these variables?

Thanks,
David (knodel@spot.Colorado.EDU)

merlyn@iwarp.intel.com (Randal L. Schwartz) (04/12/91)

In article <knodel.671412777@spot.Colorado.EDU>, knodel@news (KNODEL DAVID) writes:
| 
| In a perl application I am writing, I would find it extremely useful
| to reference variables whose names are stored in an array.  The only
| way which consistently worked was to use an eval statement.  For example,
| if I have an array:
| 
| @names=("john","joe","paul");
| 
| and I want to assign values to the variables whose names appear
| in the array (in this case, $john, $joe, and $paul).  I found that
| I could reference them via an eval statement, like:
| print eval("\$$names[0]");
| 
| but assigning to them via this method was a little gross:
| 
| eval("\$$names[0] = \"something\");
| 
| Is there a better way to reference these variables?

Sure, use symbolname assignment (or whatever it's called...):

*NAME = $names[0];

$NAME = "something";

Warning: this hides @NAME, %NAME, &NAME, and the NAME filehandle (did
I leave anything out???), so use carefully.

*NAME = *STDOUT; print NAME "Just another Perl hacker,"
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/

les@chinet.chi.il.us (Leslie Mikesell) (04/12/91)

In article <knodel.671412777@spot.Colorado.EDU> knodel@spot.Colorado.EDU writes:

>In a perl application I am writing, I would find it extremely useful
>to reference variables whose names are stored in an array.  The only
>way which consistently worked was to use an eval statement.

I've found that most places where you might want to do this are easier
to handle with associative arrays.

>For example,
>if I have an array:
>@names=("john","joe","paul");
>and I want to assign values to the variables whose names appear
>in the array (in this case, $john, $joe, and $paul).  I found that
>I could reference them via an eval statement, like:
>print eval("\$$names[0]");

For associative arrays the name itself is the key that is used to
reference the associated value and expansion of a different variable
into the key is just $array{$variable}, which can be used for
reference or assignment without any special tricks.   

>but assigning to them via this method was a little gross:
>eval("\$$names[0] = \"something\");
>Is there a better way to reference these variables?

With associative arrays, you would have a %names array and you might
not even need the @names array containing the keys since you can
reference the associative elements directly: $names{"john"} = 10; or
$name = "john"; $names{$name} = 10; and you can obtain the current
list of names with the keys() operator: @names = keys(%names); if
you happen to need it.  Since you can iterate over all the defined
elements of an associative array, you probably only need the list
of keys if you want to sort them: @names = sort(keys(%names));
This is the kind of stuff that makes using perl fun.  No need to
pre-allocate anything - just read your input into variables, then
assign or total to the values associated with the constructed keys.

Les Mikesell
  les@chinet.chi.il.us

lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (04/13/91)

In article <1991Apr12.023355.2449@iwarp.intel.com> merlyn@iwarp.intel.com (Randal L. Schwartz) writes:
: Sure, use symbolname assignment (or whatever it's called...):
: 
: *NAME = $names[0];
: 
: $NAME = "something";
: 
: Warning: this hides @NAME, %NAME, &NAME, and the NAME filehandle (did
: I leave anything out???), so use carefully.

You left out the NAME format, the NAME directory handle, and all the special
variables bound to the NAME filehandle by select.  NAME also loses any
magical significance: *ENV = 'foo' would turn %ENV into a normal array,
I believe.  (Although it's still forced to be a global variable by the
symbol table routines.)

Larry

gpvos@cs.vu.nl (Gerben 'P' Vos) (04/16/91)

lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) writes:

>                                                   NAME also loses any
>magical significance: *ENV = 'foo' would turn %ENV into a normal array,
>I believe.  (Although it's still forced to be a global variable by the
>symbol table routines.)

Also bindings with dbm files?
That * stuff sounds awful.

. . . . . . . . . . . . . . . . . . . . . . . . . . . G e r b e n   V o s   <><
Aconet: BIGBEN!Gerben Vos  Internet: gpvos@cs.vu.nl
"You know, by the time you get some with all this, the 'Swiss Army
 Chainsaw' is going to be more like a Swiss Army Tactical Nuke...."
                                        -- Brandon S. Allbery

tchrist@convex.COM (Tom Christiansen) (04/16/91)

From the keyboard of gpvos@cs.vu.nl (Gerben 'P' Vos):
:Also bindings with dbm files?
:That * stuff sounds awful.

No, only variables with "magic" names, like SIG and ENV.  Dbm bindings
still work fine -- I in fact use this.

But listen guys, I seriously suggest avoiding *foo notation unless and
until you're darn sure you know what's going on.  Pass-by-name is one of
the most obscure things in the whole language.  Combine that with dynamic
scoping, put it in the hands of a novice used to C or awk, and you're just
asking for trouble.  I use it, and I'm glad it's there for the efficiency
tweaks and functionality it gives me, but it's one of the harder things to
teach, and I usually just get groans out of the audience.

--tom

flee@cs.psu.edu (Felix Lee) (04/16/91)

One of the worst things about *var assignment is Perl doesn't have
decent garbage collection.  Try the following:
	sub a { 1; }
	*a1 = *a;
	undef &a;
	print &a1();

This example is small and obvious, but if you do anything large and
complex with * references, problems like this happen all the time.
--
Felix Lee	flee@cs.psu.edu

rbj@uunet.UU.NET (Root Boy Jim) (04/17/91)

In tchrist@convex.COM (Tom Christiansen) writes:
?From the keyboard of gpvos@cs.vu.nl (Gerben 'P' Vos):
?:Also bindings with dbm files?
?:That * stuff sounds awful.
?
?But listen guys, I seriously suggest avoiding *foo notation unless and
?until you're darn sure you know what's going on.  Pass-by-name is one of
?the most obscure things in the whole language.  Combine that with dynamic
?scoping, put it in the hands of a novice used to C or awk, and you're just
?asking for trouble.  I use it, and I'm glad it's there for the efficiency
?tweaks and functionality it gives me, but it's one of the harder things to
?teach, and I usually just get groans out of the audience.

I too had trouble with the concept, until I realized that what you're
really doing is PASSING THE SYMBOL. Lisp poeple will have no trouble
with that, nor will dynamic scoping bother them.

Another way to explain it is pretend that the expression "&a = &b"
is legal in C (so "&a = &b; a = 1;" sets b to 1), or compare it to
the reference mechanism in C++. 

I used to like C until I rediscovered Lisp. And that's why emacs
is so nice, cuz you get to code in Lisp.
-- 
		[rbj@uunet 1] stty sane
		unknown mode: sane

oz@yunexus.yorku.ca (Ozan Yigit) (04/24/91)

In article <129284@uunet.UU.NET> rbj@uunet.UU.NET (Root Boy Jim) writes:
> ... Lisp poeple will have no trouble
>with that, nor will dynamic scoping bother them.

Only if they have static scoping as well, ;-) elisp and similar subdialects
notwithstanding.

oz