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

I have created a hash of arrays. Now I want to turn each entry in each array into a hash returned by the sub 'extrct()' (Line is $$curr_struct_pos{$type[$a] = extrct();). The hashes in the array are named the same as the original strings in the array. The code is as follows:
for $type (keys %$curr_struct_pos) { for ($a=1;$$curr_struct_pos{$type}[$a];$a++) { $path = "Global${type}Def:$$curr_struct_pos{$type}[$a] +.def"; $$curr_struct_pos{$type}[$a] = extrct(); } }

Replies are listed 'Best First'.
Re: Complex Data Structures
by dragonchild (Archbishop) on Aug 30, 2001 at 19:40 UTC
    for $type (keys %$curr_struct_pos) { for ($a=1;$curr_struct_pos->{$type}[$a];$a++) { $path = "Global${type}Def:$curr_struct_pos{$type}->[$a +].def"; $curr_struct_pos->{$type}[$a] = extrct(); } }
    Check out the -> in the code.

    Also, use strict and warnings. They might have caught this problem for you.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Vote paco for President!

      There is no -> in my code (at least not on my screen). I have reposted it under 'Complex Data Structures 2' and I would appreciate it if you would have a look. Thanks.
Re: Complex Data Structures
by demerphq (Chancellor) on Aug 30, 2001 at 23:41 UTC
    Ok, well. Lets see.

    use warnings;
    use strict;

    NEVER write anything with using strict and warnings, (at least until you dont have to ask questions like this :-)
    Ok so now we have that out of the way, lets look at the code. Unless your description of what you want to do and what you are doing it with is completely wrong then you have some problems with your code, problems which frankly make it hard to give you a solution.
    Heres your code broken down into lines.
    for $type (keys %$curr_struct_pos) {

    You should use the my keyword. Combined with use strict it keeps you from misspelling variables and wondering why the code has broken (amongst many other things.)
    for ($a=1;$$curr_struct_pos{$type}[$a];$a++) {

    This has two problems, the first being that it is not _really_ perl, but cish-perl. (A sea pearl! 8-) Its not wrong, but of a style that makes a perl programmer wonder what special things you are doing to need to use this form of 'for'. But as you arent doing anything special so it probably better to to use the more commonly used list form.
    for my $var ($begin..$end) {#blah}
    Overlooking that, there is a subtle error that could _really_ cause you problems if you use the sort function.(especially as you arent using my or strict or warnings)
    The error I am refering to is the use of the dynamic (AKA global) variable $a.
    Perl uses the global variables $a and $b to pass elements of a sort into a custom block, as below:
    my @sorted=sort {$a <=> $b} @numlist;
    Notice the 'my'? :-)
    A question regarding this is should $a really be inited to 1? Arrays in perl start at 0 normally.
    Ok the next thing is just exactly what do you mean by:
    $$curr_struct_pos{$type}[$a]
    I have a feeling that you think this means something that it does not. Do you think it refers to the element $a of the array stored against the key $type in some hash? Well it doesnt. The $$cur_struct_pos{... actually is a symref to whatever the scalar $cur_struct_pos happens to point at. To prove it run the following code:
    use strict; use warnings; my %curr_struct_pos; my $curr_struct_pos="hello"; my $type="key"; my $index=0; $$curr_struct_pos{$type}[$index]++;
    Which will produce the error:
    Can't use string ("hello") as a HASH ref while "strict refs" in use at D:\Development\Perl\google\monk1.pl line 8.
    So you will have to rewrite that... Maybe like $curr_struct_pos{$type}->$index;
    $path = "Global${type}Def:$$curr_struct_pos{$type}[$a].def";
    Ok so the same issue as before with $$curr_struct_pos. use strict; use warnings; !!!!!! And basically the rest of the code is ununderstandable because of this error.
    I will provide you with what I THINK you are trying to do and maybe you can correct me.
    for my $type (keys %$curr_struct_pos) { for my $index (1..@{$cur_struct_pos{$type}}-1) { $path="Global".$type. "Def:".$curr_struct_pos{$type}[$a]. ".def"; #much easier to read $curr_struct_pos{$type}[$a] = extract(); }
    Now I understand you want to take the strings in the array and turn them into keys in a hash right? Well in general terms this is how you would do it (its a FAQ BTW);
    my %hash; my @list=qw(These elements are going to become keys); map {$hash{$_}++} @list; #or $hash{$_}++ foreach @list; #or with refs... my $hash_ref =\%hash; my $array_ref=\@list; $hash->{$_}++ foreach @$list;

    So to sum up I would say that you should go over perlreftut very carefully once again (you _have_ read it right?), and
    use strict; use warnings; until you can send me a mail telling me why you dont think you should have to, and being correct in what you say.
    Im sorry I dont mean to be a bitch, but the golden rule that all the newbies break is this one. Virtually all of their problems disappear when they start using it.
    HTH
    Yves
    --
    You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)
      I apologise. I noticed a minor problem in my interpretation of your code. So assuming that the hash we are dealing with is defined something like:
      my %curr_struct_pos;
      Then this should do:
      for my $type (keys %curr_struct_pos) { for my $index (0..@{$cur_struct_pos{$type}}-1) { $path="Global".$type. "Def:".$curr_struct_pos{$type}->[$a]. ".def"; $curr_struct_pos{$type}->[$a] = extract(); }
      On the other hand if it is a reference to a hash that you have there then this should do:
      for my $type (keys %$curr_struct_pos) { for my $index (0..@{$cur_struct_pos->{$type}}-1) { $path="Global".$type. "Def:".$curr_struct_pos->{$type}[$a]. ".def"; $curr_struct_pos->{$type}[$a] = extract(); }
      As for extract() I believe you can work that one out for yourself from my other post.

      Yves
      --
      You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)
        Thanks for the replies. I will have a look at it but I think I am going to use a different data structure instead. I promise I will use strict and warnings in future. Just for the record the variables were
        $curr_struct_pos = "string"; %$curr_struct_pos;
        and I wanted the new hash to have the same name as the string in the array - not the keys of the hash. Also
        $path = "Global${type}Def:$$curr_struct_pos{$type}[$a].def";
        does give me the correct paths. I have only been using Perl for less than two weeks so forgive my Cish Perl.