[comp.lang.perl] Variable variables

zwicky@sparkyfs.itstd.sri.com (Elizabeth Zwicky) (02/16/90)

I have an array, @devices, consisting of a list of device names read
from the command line. For each of those devices, I need an array
consisting of the machines supposed to be backed up to that device.
What I would like to do is something like this, were this grammatical:
	
	foreach $device (@devices){
      		@$device = something;
        }

Assuming that @devices had two strings in it, "foo" and "bar" this
should create @foo and @bar.  I can do this for scalars via an
associative array (i.e., to set things up so that I can check whether
a device is free or not, I have an associative array with keys named
after the devices), but I am at a loss as to how to cope for arrays.

	Elizabeth Zwicky

merlyn@iwarp.intel.com (Randal Schwartz) (02/16/90)

In article <29987@sparkyfs.istc.sri.com>, zwicky@sparkyfs (Elizabeth Zwicky) writes:
| I have an array, @devices, consisting of a list of device names read
| from the command line. For each of those devices, I need an array
| consisting of the machines supposed to be backed up to that device.
| What I would like to do is something like this, were this grammatical:
| 	
| 	foreach $device (@devices){
|       		@$device = something;
|         }

Pretty darn close for guessing.  Try:

for $device (@devices) {
	eval '@' . $device . ' = something';
}

But, how are you going to get the values back out?  I've done similar
stuff, and the fastest ends up looking like:

for $device (@devices) {
	$dev{$device} = "some space separated values";
}

and then when I'm working on device foo:

	@values = split(/ /,$dev{'foo'});

to get the array back.  Use whatever delimiter doesn't appear in your
values.

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: "Welcome to Portland, Oregon, home of the California Raisins!"=/

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/16/90)

In article <29987@sparkyfs.istc.sri.com> zwicky@sparkyfs.itstd.sri.com (Elizabeth Zwicky) writes:
: I have an array, @devices, consisting of a list of device names read
: from the command line. For each of those devices, I need an array
: consisting of the machines supposed to be backed up to that device.
: What I would like to do is something like this, were this grammatical:
: 	
: 	foreach $device (@devices){
:       		@$device = something;
:         }
: 
: Assuming that @devices had two strings in it, "foo" and "bar" this
: should create @foo and @bar.  I can do this for scalars via an
: associative array (i.e., to set things up so that I can check whether
: a device is free or not, I have an associative array with keys named
: after the devices), but I am at a loss as to how to cope for arrays.

I'd suggest

	foreach $device (@devices) {
	    eval "\@$device = something";
	}

Larry

jgreely@oz.cis.ohio-state.edu (J Greely) (02/16/90)

In article <1990Feb15.195712.6845@iwarp.intel.com> merlyn@iwarp.intel.com
 (Randal Schwartz) writes:
>In article <29987@sparkyfs.istc.sri.com>, zwicky@sparkyfs (Elizabeth Zwicky) writes:
>| 	foreach $device (@devices){
>|       		@$device = something;
>|         }

>for $device (@devices) {
>	eval '@' . $device . ' = something';
>}

Just for fun, if you want to do more complicated things to the
individual elements, here's a twisted example that uses my favorite
Perl feature:

	@devices=("dev1","dev2");
	@dev1=("dev1.1","dev1.2");
	@dev2=("dev2.1","dev2.2");
	grep(eval <<EOF,@devices);
	foreach \$field (@$_) {
		print "$_: \$field\n";
	}
	EOF

I find that using << makes it easier to debug my evals, and creative
use of grep just gives me the giggles (it would be particularly
interesting to make use of source-array modification in this example,
but I'll resist this time).


			"I stopped thinking of HyperTalk as a
			 real programming language when I
			 realized that 'get line 1 of card
			 field short name of the target' was
			 *concise*."
--
J Greely (jgreely@cis.ohio-state.edu; osu-cis!jgreely)

tneff@bfmny0.UU.NET (Tom Neff) (02/16/90)

In article <29987@sparkyfs.istc.sri.com> zwicky@sparkyfs.itstd.sri.com (Elizabeth Zwicky) writes:
>I have an array, @devices, consisting of a list of device names read
>from the command line. For each of those devices, I need an array
>consisting of the machines supposed to be backed up to that device.

You could use 'eval' to create arrays whose names were derived from the
device names, and to refer to their contents later on.

Another approach would be to create an associative array, indexed by
device name, where the associated element is a string of the form
"machine1,machine2,machine3...".  The 'join' and 'split' operators make
the transformation between a string of this form and a straight
@machines array straightforward.

I would go with the second approach.

markb@agora.UUCP (Mark Biggar) (02/21/90)

In article <29987@sparkyfs.istc.sri.com> zwicky@sparkyfs.itstd.sri.com (Elizabeth Zwicky) writes:
>I have an array, @devices, consisting of a list of device names read
>from the command line. For each of those devices, I need an array
>consisting of the machines supposed to be backed up to that device.
>What I would like to do is something like this, were this grammatical:
>	
>	foreach $device (@devices){
>      		@$device = something;
>        }

Beside the various solutions using eval, you can also use the index
concatenation feature of associative arrays
	
	$i = 1;
	foreach $device (@devices) {
		$DEV{$device,$i++} = something;
	}

The elements of the list in the {} are concatenated to produce the actual
index string used (as opposed to @DEV{$x,$y} which produces the list of 
elements selected.)  This feature can be used to produce may useful data
structures like sparce and ragged arrays.  Constant separaters can easily be 
introduced to the list to allow parsing actual indecies out of the 
index returned from keys().

--

FROM SOMEONE THERE AT THE BEGINING
Mark Biggar