[kw-pm] Problem with hash

Eric Maki eric at uc.org
Wed Jul 29 13:09:42 PDT 2009


If you are curious about what Perl thinks you want it to do, toss

print Dumper \%text;

at the end of your program:

$VAR1 = {
           'SYSTEM' => 'TEXT'
         };

This is because:

$prodFnd{"101010"}{"S0"} = "text";

and then

$prodFnd{"101010"}{"S0"}{"SYSTEM"} = "TEXT";

because you are 'use strict;'ing, soft references are allowed, so

$prodFnd{"101010"}{"S0"}{"SYSTEM"} = "TEXT";

means

$text{"SYSTEM"} = "TEXT";

So, you just created a hash named %text and assigned to it.

use strict 'refs'; was introduced because that behaviour is 
very frequently not what you want.

Eric


---- original message : 2009-07-29 3:52pm : abez ----

> Perl is doing exactly what you told it to do. The problem is that you
> made a mistake and you didn't your code carefully enough to see it.
>
> do you see how you're testing {"SYSTEM"}, that's a key in "S0"'s hash.
>
> Except you assigned "S0" to a scalar.
>
> you're actually trying to overwrite a scalar with a hash that looks like
> this:
>
> {
>   SYSTEM => "TEXT"
> }
>
> when you go $prodFnd{$a}{$b}{SYSTEM} = $c;
> you really mean is
>
> $prodFnd{$a}->{$b}->{SYSTEM} = $c;
>
> but $prodFnd{$a}->{$b} is not hash/hashref!
>
> You made $prodFnd{$a}->{$b} be "text";
> not { SYSTEM => "text" }. There's a difference.
>
> Perl is auto-vivifying your hash. It brings it to life, it generates new
> hashes.
>
> Just run this and you'll see that your initial assignments are to things
> you're not even looking for. Step through it. Look at it. You don't even
> have the same strings.
>
>  use Data::Dumper;
>  $prodFnd{"101010"}{"S0"} = "text";
>  $prodFnd{"101010USED"}{"S0"} = "text";
>  print Dumper(\%prodFnd); #Do you see "SYSTEM" anywhere? No!
>  if (!exists($prodFnd{"101010"}{"S0"}{"SYSTEM"})) {
>      $prodFnd{"101010"}{"S0"}{"SYSTEM"} = "TEXT";
>      print "First<br>";
>      print Dumper(\%prodFnd); #you see "SYSTEM" now? No!
>  }
>  if (!exists($prodFnd{"101010USED"}{"S0"}{"SYSTEM"})) {
>      $prodFnd{"101010USED"}{"S0"}{"SYSTEM"} = "TEXT";
>      print "Second<br>";
>      print Dumper(\%prodFnd); #you see "SYSTEM" now? No!
>  }
>
> Then run
>  use strict;
>  use Data::Dumper;
>  $prodFnd{"101010"}{"S0"} = "text";
>  $prodFnd{"101010USED"}{"S0"} = "text";
>  print Dumper(\%prodFnd);
>  if (!exists($prodFnd{"101010"}{"S0"}{"SYSTEM"})) {
>      $prodFnd{"101010"}{"S0"}{"SYSTEM"} = "TEXT";
>      print "First<br>";
>      print Dumper(\%prodFnd);
>  }
>  if (!exists($prodFnd{"101010USED"}{"S0"}{"SYSTEM"})) {
>      $prodFnd{"101010USED"}{"S0"}{"SYSTEM"} = "TEXT";
>      print "Second<br>";
>      print Dumper(\%prodFnd);
>  }
>
> See all those warnings and errors? Fix those!
>
> If you had "use strict;" like recommended this would never have run
> anyways because "S0" would not be a hash so you couldn't ask it for values.
>
> Summary: Hashes are not scalars, scalars are not hashes, use strict
>
> For more help, type:
> perldoc perldata
> and
> perldoc -f exists
>
> Or go google for perldoc perldata.
>
> abram
>
>
>
> Robert Pike wrote:
>> Sorry. I actually changed the name of the variables because of the data and such used (sensitive and such). I've simplified the problem I'm having below using the actual data retrieved from the array I'm using in this test.
>>
>> $prodFnd{"101010"}{"S0"} = "text";
>> $prodFnd{"101010USED"}{"S0"} = "text";
>> if (!exists($prodFnd{"101010"}{"S0"}{"SYSTEM"})) {
>>     $prodFnd{"101010"}{"S0"}{"SYSTEM"} = "TEXT";
>>     print "First<br>";
>> }
>> if (!exists($prodFnd{"101010USED"}{"S0"}{"SYSTEM"})) {
>>     $prodFnd{"101010USED"}{"S0"}{"SYSTEM"} = "TEXT";
>>     print "Second<br>";
>> }
>>
>> This will only print First. I had also tried defined to see what I got and the same thing occured. I tried changing 101010USED to something else in the second if and it passed, changed only S0 to something else and it passed, and the same with SYSTEM and it passed. What am I missing? Thank you so much for the response and help as well. I also tried the data dump and it gave me what I expected. If I printed out what was in $prodFnd{"101010USED"}{"S0"}{"SYSTEM"} after the first if block it would actually print "TEXT". Does Perl ignore the letters after it sees letters in the first level of the hash or something?
>>
>>
>>
>> --- On Wed, 7/29/09, abez <abez at abez.ca> wrote:
>>
>>> From: abez <abez at abez.ca>
>>> Subject: Re: [kw-pm] Problem with hash
>>> To: "Robert Pike" <roberthpike at yahoo.com>
>>> Cc: "KW Perl Mongers" <kw-pm at pm.org>
>>> Received: Wednesday, July 29, 2009, 2:52 PM
>>>
>>> This doesn't parse:
>>>
>>>> for (my $cC=0$cC<=$#aA;$cC++) {
>>> Space everything out, I think you're missing a semi-colon
>>>
>>> for ( my $cC = 0 ; $cC <= $#aA ; $cC++ ) {
>>>
>>> put use strict; up at the top. It'll tell you that vHash !=
>>> vHsh
>>> (misspelling).
>>>
>>> Then add a:
>>>
>>> use Data::Dumper;
>>> print Dumper(\%vHsh);
>>>
>>> at the end of your program and you'll see the hash it
>>> makes.
>>> You'll notice you're checking for SS0 and S0 because you
>>> have this
>>> "S".$item2 everywhere.
>>>
>>> As well you're checking for $vHsh{$itm1}{$itm2}{"SYSTEM"}
>>> but in your
>>> examples you never set "SYSTEM", you in fact set
>>> $vHsh{$itm1}{$itm2} to
>>> a scalar value, not a hashref
>>>
>>> "use strict;" will attempt to spell check your variables. I
>>> recommend
>>> always using it.
>>>
>>> I've attached my code at the end of this message.
>>>
>>> abram
>>>
>>>
>>> Robert Pike wrote:
>>>> First off, thanks to all that supplied me with
>>> feedback in regards to the issue I was having with
>>> redirection in perl.
>>>> I loop through an array, split the values, and put
>>> certain values in a hash. Hopefully this will be enough info
>>> to get some feedback.
>>>> my %vHash;
>>>> $vHsh{"101010"}{"S0"} = "text";
>>>> $vHsh{"101010USED"}{"S0"} = "text";
>>>>
>>>> my @aA = ("101010~S0", "101010USED~S0");
>>>> #if I were to do this
>>>> for (my $cC=0$cC<=$#aA;$cC++) {
>>>>      ($itm1, $itm2) =
>>> split(/\~/,$aA[$cC]);
>>>>      if
>>> (!exists($vHsh{$itm1}{"S".$itm2}{"SYSTEM"})) { #--- also
>>> tried defined
>>>>
>>>    $vHsh{$itm1}{"S".$itm2}{"SYSTEM"} =
>>> "TEXT";
>>>>      }
>>>> }
>>>>
>>>>      The if statement (with the
>>> defined/exists check) criteria passes first pass but fails
>>> in the second. Can anyone tell me why?
>>>>
>>>>
>>>    __________________________________________________________________
>>>> Connect with friends from any web browser - no
>>> download required. Try the new Yahoo! Canada Messenger for
>>> the Web BETA at http://ca.messenger.yahoo.com/webmessengerpromo.php
>>>> _______________________________________________
>>>> kw-pm mailing list
>>>> kw-pm at pm.org
>>>> http://mail.pm.org/mailman/listinfo/kw-pm
>>> use strict;
>>> use Data::Dumper;
>>> { #make a new scope
>>>   # this version does not work properly
>>>   # this is a minor modification to the original
>>> version
>>>   my %vHsh;
>>>   $vHsh{"101010"}{"S0"} = "text";
>>>   $vHsh{"101010USED"}{"S0"} = "text";
>>>
>>>   my @aA = ("101010~S0", "101010USED~S0");
>>>   #if I were to do this
>>>   my ($itm1, $itm2); #satisfy use strict
>>>   for (my $cC=0;$cC<=$#aA;$cC++) {
>>>       ($itm1, $itm2) =
>>> split(/\~/,$aA[$cC]);
>>>       if
>>> (!exists($vHsh{$itm1}{"S".$itm2}{"SYSTEM"})) { #--- also
>>> tried
>>> defined
>>>       warn "Found [$itm1 $itm2]";
>>>
>>> $vHsh{$itm1}{"S".$itm2}{"SYSTEM"} = "TEXT";
>>>       }
>>>   }
>>>   print Dumper(\%vHsh);
>>> }
>>>
>>> print "$/ Now again but correctly $/";
>>> {
>>>   # this is the new verison
>>>   my %vHsh;
>>>   $vHsh{"101010"}{"S0"}{"SYSTEM"} = "TEXT";
>>>   $vHsh{"101010USED"}{"S0"}{"SYSTEM"} = "TEXT";
>>>
>>>   my @aA = ("101010~S0", "101010USED~S0");
>>>   #if I were to do this
>>>   for ( my $cC = 0 ; $cC <= $#aA ; $cC++ ) {
>>>       my ($itm1, $itm2) =
>>> split(/\~/,$aA[$cC]); # note the scope
>>>       if
>>> (!exists($vHsh{$itm1}{$itm2}{"SYSTEM"})) { #--- also tried
>>> defined
>>>       warn "Found [$itm1 $itm2]";
>>>
>>> $vHsh{$itm1}{$itm2}{"SYSTEM"} = "TEXT";
>>>       }
>>>   }
>>>   print Dumper(\%vHsh);
>>> }
>>>
>>>
>>>
>>>
>>>
>>
>>
>>       __________________________________________________________________
>> Yahoo! Canada Toolbar: Search from anywhere on the web, and bookmark your favourite sites. Download it now
>> http://ca.toolbar.yahoo.com.
>  use strict;
>  use Data::Dumper;
>  my %prodFnd;
>  $prodFnd{"101010"}{"S0"} = "text";
>  $prodFnd{"101010USED"}{"S0"} = "text";
>  print Dumper(\%prodFnd);
>  if (!exists($prodFnd{"101010"}{"S0"}{"SYSTEM"})) {
>      $prodFnd{"101010"}{"S0"}{"SYSTEM"} = "TEXT";
>      print "First<br>";
>      print Dumper(\%prodFnd);
>  }
>  if (!exists($prodFnd{"101010USED"}{"S0"}{"SYSTEM"})) {
>      $prodFnd{"101010USED"}{"S0"}{"SYSTEM"} = "TEXT";
>      print "Second<br>";
>      print Dumper(\%prodFnd);
>  }
>
>
>


More information about the kw-pm mailing list