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

This is the first time that I have attempted to use complex data structures in Perl, and I bet I have made some small mistake. Below is what I believe is the significant code, from structure declaration to the attempted assignment. I have diagnostics and strict on.
my %member_info = ( mid=>undef, created_info=>{created_by=>undef, created_date=>undef,}, modified_info=>{modified_by=>undef, modified_date=>undef,}, person=>[ 0=>{salutation=>undef, first_name=>undef, middle_initial=> +undef, last_name=>undef, date_of_birth=>undef, primary_language=>unde +f, secondary_language=>undef, marital_status=>undef, working=>undef, + family_size=>undef, home_days=>undef, leader=>undef, default=>undef, +}, ], school=>[ 0=>{school_type=>"school", school_name=>undef, gradua +tion_date=>undef}, 1=>{school_type=>"school1", school_name=>undef, gradu +ation_date=>undef}, ], ); # declaring it just so I don't forget $response = $browser->get("https://infoishere.org/tails.asp?" . $_ +) if m/^\d+$/; $toke_parse = HTML::TokeParser->new( \$response->content ); #tokeparse full document, fill structure with data while($token = $toke_parse->get_token){ #match the table id's to start per-table loops next unless ($token->[0] eq 'S' and $token->[1] eq 'table'); # +only test table start tokes, skip other tokes if(($token->[0] eq "S") and ($token->[4] =~ m/id.{1,3}table13/ +i)){ #member unique id and name $token = $toke_parse->get_token until(($token->[0] eq "E") and + ($token->[1] =~ m/tr/i)); # end header row #debugging print Dumper(\%member_info); $member_info{'person'}[0]{'salutation'} = &skip_to_cell_text( +1 ); # error on this line $member_info{'person'}[0]{'first_name'} =&skip_to_cell_text( 1 + ); $member_info{'person'}[0]{'middle_initial'} = &skip_to_cell_te +xt( 1 ); [...]
The Dump:
$VAR1 = { 'modified_info' => { 'modified_date' => undef, 'modified_by' => undef }, 'created_info' => { 'created_date' => undef, 'created_by' => undef }, 'person' => [ 0, { 'middle_initial' => undef, 'salutation' => undef, 'leader' => undef, 'marital_status' => undef, 'date_of_birth' => undef, 'last_name' => undef, 'family_size' => undef, 'primary_language' => undef, 'default' => undef, 'secondary_language' => undef, 'home_days' => undef, 'first_name' => undef } ], 'school' => [ 0, { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'school' }, 1, { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'school1' } ], 'mid' => undef };


The error:
Can't use string ("0") as a HASH ref while "strict refs" in use at ./prog line 136 (#1)
(F) Only hard references are allowed by "strict refs". Symbolic references are disallowed. See perlref.

The Mystery:
It looks like it is a hash that points to an array that contains a hash, and that is what I want. The 0 is an array ref, not a hash. Why is my assignment causing an error?

Replies are listed 'Best First'.
Re: Mistake in data structure use?
by suaveant (Parson) on Dec 01, 2006 at 20:54 UTC
    'school' => [ 0, { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'school' }, 1, { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'school1' } ],
    You are preceding the hashes in the array with their indexes... this is almost certainly not what you want. in square brackets items are assigned their array index by position... first is index 0, second is index 1, etc...

    it should look like

    'school' => [ { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'school' }, { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'school1' } ],

                    - Ant
                    - Some of my best work - (1 2 3)

      The part you quote and say I should change is the dump from Data::Dumper, the code is above that.

      I do really need help with this one, I worked on it all last night, but I think it is just something that I don't know and need to be pointed in the right direction.

        Data::Dumper does it like that because your code does it like that:

        school=>[ 0=>{school_type=>"school", school_name=>undef, graduation_da +te=>undef}, 1=>{school_type=>"school1", school_name=>undef, graduation_d +ate=>undef}, ],

        The other poster is suggesting you do it this way:

        school=>[ {school_type=>"school", school_name=>undef, graduation_date=> +undef}, {school_type=>"school1", school_name=>undef, graduation_date= +>undef}, ],

        However, if that's not the problem, perhaps you should tell us which line exactly is line 136. I could not tell this easily from your original post. perl's error messages tell you the line number for a reason.


        Sanity? Oh, yeah, I've got all kinds of sanity. In fact, I've developed whole new kinds of sanity. You can just call me "Mister Sanity". Why, I've got so much sanity it's driving me crazy.
Re: Mistake in data structure use?
by chargrill (Parson) on Dec 01, 2006 at 23:46 UTC

    McLogic,

    I've shortened your example and tidied it up a bit (and made it fit in the standard PM node code width) and made a few changes. First, the code:

    #!/usr/bin/perl use strict; use warnings; my %member_info = ( mid => undef, created_info => { created_by => undef, created_date => undef, }, modified_info => { modified_by => undef, modified_date => undef, }, person => { salutation => undef, first_name => undef, middle_initial => undef, }, school => [ { school_type => "school", school_name => undef, graduation_date => undef }, { school_type => "school1", school_name => undef, graduation_date => undef }, ], ); $member_info{'person'}{'salutation'} = "test"; $member_info{'school'}[0]{'school_type'} = "testing"; $member_info{'school'}[1]{'school_type'} = "testing2"; use Data::Dumper; print Dumper \%member_info; OUTPUT: $VAR1 = { 'mid' => undef, 'modified_info' => { 'modified_date' => undef, 'modified_by' => undef }, 'created_info' => { 'created_date' => undef, 'created_by' => undef }, 'person' => { 'middle_initial' => undef, 'salutation' => 'test', 'first_name' => undef }, 'school' => [ { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'testing' }, { 'graduation_date' => undef, 'school_name' => undef, 'school_type' => 'testing2' } ] };

    So as you can see, I'm able to set values for your HoAoH and/or HoH's.

    Alternatively, you could do something like:

    ... school => { 0 => { school_type => undef }, 1 => { ... } }, ...

    But then you'd have to access it via:  $member_info{'school'}{0}{'school_type'}. But that seems less clear and more muddled than you'd probably want, and won't keep your schools in order as the array would.



    --chargrill
    s**lil*; $*=join'',sort split q**; s;.*;grr; &&s+(.(.)).+$2$1+; $; = qq-$_-;s,.*,ahc,;$,.=chop for split q,,,reverse;print for($,,$;,$*,$/)