[kw-pm] Problem with hash

Eric Maki eric at uc.org
Wed Jul 29 13:15:39 PDT 2009


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

I meant because you are not 'use strict;'ing

See perldoc strict "strict refs" for a discussion of symbolic 
references.

---- original message : 2009-07-29 4:09pm : Eric Maki ----

>
> 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);
>>  }
>> 
>> 
>> 
> _______________________________________________
> kw-pm mailing list
> kw-pm at pm.org
> http://mail.pm.org/mailman/listinfo/kw-pm
>


More information about the kw-pm mailing list