Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Extending a hash

by dingbob (Initiate)
on Apr 21, 2011 at 10:09 UTC ( #900562=perlquestion: print w/replies, xml ) Need Help??
dingbob has asked for the wisdom of the Perl Monks concerning the following question:


Noob question, so please be kind, oh frocked ones...

Given the code
use strict; use warnings; my %hash; $hash{a} = 'bob'; $hash{b} = 'mary'; $hash{a}[0] = 1;
I get the error Can't use string ("bob") as an ARRAY ref while "strict refs" in use at 1 line 9., which is expected (after much googling, I understand why).

However, from the code I'm sure you can understand what I'm trying to achieve. ie, associate the value '1' with key 'a'. Using the keys 'a' and 'b' is important since they're being read from a config file.

ie, basic config may look like:
a = bob b = mary
extended config:
a = bob a = 1 b = mary
When building my %hash, if $hash{a} is already defined, then I want to store any duplicate key names in the hash (hence my reaching for an array).

I'm a bit stumped and need a fresh perspective.

Any ideas?


Replies are listed 'Best First'.
Re: Extending a hash
by moritz (Cardinal) on Apr 21, 2011 at 10:23 UTC
Re: Extending a hash
by SimonClinch (Deacon) on Apr 21, 2011 at 10:21 UTC
    $hash{a} may either valuate to a scalar or an array reference but not both, at least not in the way you present - Perl is trying to interpret bob as an array reference and bombing out with a slightly confusing error message. I would tend to make it always valuate to an array reference, even if there is only one value, e.g.
    use strict; use warnings; my $cfg = ARGV[0] or die "Usage: $0 <config_file>\n"; my %hash; open my $ch, $cfg or die "$!: $cfg\n"; while( <$ch> ) { chomp; my ($k, $v) = split /\s+/; $hash{k} ||= []; push @{ $hash{$k}}, $v; } close $ch;

    One world, one people

      Perl is trying to interpret bob as an array reference and bombing out with a slightly confusing error message.
      I must disagree, I don't think it is confusing, once you understand what's going on.

      Perl has a feature to use symbolic references, i.e. a variable may contain the name of a global variable and you can access its contents through it. For example:

      our $red = 10; our $green = 6; my $apples = 'red'; $$apples--; # eat an apple print "I've got $red red apples, and $green green ones.\n";
      I've got 9 red apples, and 6 green ones.

      It's a powerful system but abusing it is not a good idea. That's why strict prevents it by default (when you use strict;).

      What is the source of the confusion here, is that the syntax (and the code for the internals) is the same as with real references instead of strings.

      It also works with hashes and arrays for data, and with any kind of scalar as the symbolic reference. And that is what is going on here: $hash{a} contains the string 'bob' so $hash{a}[0] is trying to either use $hash{a} as an array reference (if it is a reference; or undef, which is what we usually want anyway) or, since it is a string here, as a symbolic reference to the global variable @bob. And the latter is what strict is preventing, with that error message as a result

      Try it with no strict:

      our @bob; my %hash; $hash{a} = 'bob'; $hash{a}[0] = 1; print "\@bob contains: [@bob]\n";
      which results in
      @bob contains: [1]
      Yes, I used the word "slightly" to bridge the gap between my understanding the OP's stated perspective - the confusion is obviously not mine. There is really no need for such a lecture. What is it about this site that attracts so many straw man arguments? I made an honest suggestion to help the OP. So why are you entering into a discourse on techniques you don't even encourage?

      One world, one people

Re: Extending a hash
by apl (Monsignor) on Apr 21, 2011 at 10:37 UTC
    Consider using (untested)
    $hash{a}{name} = 'bob'; $hash{a}{values}[0] = 1; $hash{b}{name} = 'mary';

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://900562]
Approved by moritz
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2018-05-21 07:31 GMT
Find Nodes?
    Voting Booth?