in reply to Dynamically allocating variables

What you're describing, symbolic variable references, is generally discouraged. You can probably get away with using a hash instead.

my %data; while (<DATA>) { chomp; my ($key, @values) = split /\s+/; $data{$key} = [ @values ]; } print $data{key2}->[1], "\n"; # prints: e __DATA__ key1 a b c key2 d e f key3 g h i

See the Perl data structure's cookbook and perllol for information about Perl's data structures.

Replies are listed 'Best First'.
Re: Re: Dynamically allocating variables
by newatperl (Acolyte) on Dec 02, 2001 at 05:36 UTC
    I'm using the stucts from Class::Struct, can I get away with just defining one struct and then reusing that struct over and over for each line? i.e. I guess my real question is, when you push something onto a Hash, does it push the value, or just a pointer? Hence, if I reuse the same struct, and the Hash just had pointers, I'd be overwriting the previous variables... Thanks.

      does it push the value, or just a pointer?

      When you're passing around objects, really you're passing around special references. So even if you have two scalars pointing to one struct, it's that same struct you're modifying, regardless of how it's named.

      It might be easier to illustrate with an example:

      use Class::Struct; use strict; struct Test => [ xyz => '$' ]; our $T = new Test(xyz => 123); print "\$T->xyz starts as: ", $T->xyz, "\n"; no strict 'refs'; my $symbolic = "T"; ${$symbolic}->xyz(456); print "\$T->xyz is now: ", $T->xyz, "\n"; my %A $A{t} = $T; $A{t}->xyz(789); print "\$T->xyz is now: ", $T->xyz, "\n"; __END__ $T->xyz starts as: 123 $T->xyz is now: 456 $T->xyz is now: 789
      To get "full" copy effects, you need to make a copy of each of the fields:
      my $a = new Test ( xyz => 123 ); # original my $b = new Test ( xyz => $a->xyz ); # copy of a $b->xyz(456); printf "a=%d b=%d\n", $a->xyz, $b->xyz; # a=123 b=456

      I don't know of an easy way to "deep copy" struct objects, though the Clone module (or Storable's 'dclone' function) may help.

        Thanks for clarifying that Fastolfe. But, I guess my original question still stands. Without turing strict off, I can't really load a Hash with unique structs that are created on the fly as I read each line in. true or not true?
      You don't really push to a hash, you can - but push is usually reserved for array (and yes, a hash is an array). My point is that you assign a value to a hash key - that value can be a scalar (the value), a reference (the pointer), or other things.

      Here is an example that reads 'configuration info' from Perl's built in DATA filehandle. I use DATA because it's easy and you only need one file for demonstrations. Anyhow, the configuration is simply two values seperated by a comma per line. The while loop processes DATA one line at a time and creates a new struct object with the values it finds. After the struct is instantiated, it is pushed to an array. Since it is already a reference there is no need to de-reference it. The last line is a for loop that prints out only one of the attributes for each struct in the array.

      use strict; use Class::Struct; # declare the struct struct(MyStruct => { even => '$', odd => '$', }); # create array of structs my @structs; while (my $line = <DATA>) { chomp $line; my ($odd,$even) = split(',',$line); my $obj = new MyStruct; $obj->odd($odd); $obj->even($even); push(@structs,$obj); } print $_->odd(), "\n" foreach (@structs); __DATA__ one,two three,four five,six seven,eight nine,ten
      But hold it right there! Why are you using Class:Struct? No offense to the author, but if you are going to code in Perl, code like Perl. Check this out:
      use strict; # create array of structs my @structs; while (my $line = <DATA>) { chomp $line; my ($odd,$even) = split(',',$line); my %hash = ( odd => $odd, even => $even, ); # i do have to de-reference %hash though push(@structs,\%hash); } print $_->{'odd'}, "\n" foreach (@structs); __DATA__ one,two three,four five,six seven,eight nine,ten
      Same thing with less lines, and i spared using map to golf it down even further ... oh what the hell:
      print $_->{odd},"\n"for map{my($o,$e)=split',',$_;{odd=>$o,even=>$e}}< +DATA>;
      Welcome to Perl. :)

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      F--F--F--F--F--F--F--F--
      (the triplet paradiddle)