perl inbuilt function "each" may be having a bug

perl inbuilt function "each" may be having a bug

am 20.08.2007 12:22:35 von al.moorthi

Hi,
This code is not working and assigning values to '' , actually it
shouldn't.
#!/usr/bin/perl
use strict;
use warnings;

my %x= (a=>{a=>1,b=>2}, c=>3);
foreach (0..3) {
my($a,$b) = each %{$x{a}};
print "A = '$a', B = '$b'\n";
}
exit(0);

perl each-bug.pl
OUTPUT IS:
A = 'a', B = '1'
A = 'b', B = '2'
Use of uninitialized value in concatenation (.) or string at each-
bug.pl line 8.
Use of uninitialized value in concatenation (.) or string at each-
bug.pl line 8.
A = '', B = ''
A = 'a', B = '1'

Re: perl inbuilt function "each" may be having a bug

am 20.08.2007 12:43:03 von Mirco Wahab

al.moorthi@gmail.com wrote:
> This code is not working and assigning values to '' , actually it
> shouldn't.

It does what it "should", imho.

> #!/usr/bin/perl
> use strict;
> use warnings;
>
> my %x= (a=>{a=>1,b=>2}, c=>3);
> foreach (0..3) {

The hash $x{$a} has only 2 elements,
the foreach (0..3) are *more* than this

> my($a,$b) = each %{$x{a}};
> print "A = '$a', B = '$b'\n";

...
my %x = ( a =>
{ a => 1,
b => 2
},
c => 3
);

for (0 .. keys(%x) - 1) { # implicit "scalar keys(...)"
my ($a, $b) = each %{ $x{a} };
print "A = '$a', B = '$b'\n"
}


Regards

M.

Re: perl inbuilt function "each" may be having a bug

am 20.08.2007 12:46:36 von Gunnar Hjalmarsson

al.moorthi@gmail.com wrote:
> This code is not working and assigning values to '' , actually it
> shouldn't.

Why shouldn't it behave in accordance with the documentation? From
"perldoc -f each":
"When the hash is entirely read, a null array is returned in list context"

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Re: perl inbuilt function "each" may be having a bug

am 20.08.2007 12:54:28 von anno4000

wrote in comp.lang.perl.misc:
> Hi,
> This code is not working and assigning values to '' , actually it
> shouldn't.

It works exactly to specification.

> #!/usr/bin/perl
> use strict;
> use warnings;
>
> my %x= (a=>{a=>1,b=>2}, c=>3);
> foreach (0..3) {
> my($a,$b) = each %{$x{a}};
> print "A = '$a', B = '$b'\n";
> }
> exit(0);
>
> perl each-bug.pl
> OUTPUT IS:
> A = 'a', B = '1'
> A = 'b', B = '2'
> Use of uninitialized value in concatenation (.) or string at each-
> bug.pl line 8.
> Use of uninitialized value in concatenation (.) or string at each-
> bug.pl line 8.
> A = '', B = ''
> A = 'a', B = '1'

Why are you using a two-level hash to demonstrate the behavior? You're
only using the inner hash. Here is a simplified version that behaves
exactly the same:

my %y = ( a => 1, b => 2);

foreach ( 0 .. 3 ) {
my ( $a, $b) = each %y;
print "A = '$a', B = '$b'\n";
}

You are calling each() four times on a hash that has only two key-value
pairs. The documentation says:

When the hash is entirely read, a null array is returned in
list context (which when assigned produces a false (0) value),
and "undef" in scalar context. The next call to "each" after
that will start iterating again. There is a single iterator

That is exactly what's happening. The first two calls act "normally".
The you get one call that leaves $a and $b undefined. Since you are
enforcing evaluation in string context, these look like empty strings.
Finally the iteration starts over and you see the first pair again.

Where is the bug?

Anno

Re: perl inbuilt function "each" may be having a bug

am 20.08.2007 12:58:40 von Mirco Wahab

al.moorthi@gmail.com wrote:
> This code is not working and assigning values to '' , actually it
> shouldn't.

It does what it "should", imho.

> my %x= (a=>{a=>1,b=>2}, c=>3);
> foreach (0..3) {
The whole hash has only 2 elements,
the hashref $x{$a} points to twe
elements, but the foreach (0..3) are
*more* than two.

> my($a,$b) = each %{$x{a}};
> print "A = '$a', B = '$b'\n";
> }
> exit(0);

At first, I didn't understand your intention
and posted a irrelevant response (which I
canceled). What I think now what you should
do in order to get along - is sth. like this:

...

my %x = ( a =>
{ a => 1,
b => 2
},
c => 3
);

for ( keys %x ) {
# print the outer hash as it is
print "k=$_, v=$x{$_}\n";

# check if the hash value is a hashref
if( UNIVERSAL::isa $x{$_},'HASH' ) {
# and bump along
while ( my ($a, $b) = each %{ $x{a} } ) {
print "\tA = '$a', B = '$b'\n";
}
}

}

....

Regards

M.

Re: perl inbuilt function "each" may be having a bug

am 20.08.2007 12:59:06 von Mirco Wahab

Mirco Wahab wrote:
> while ( my ($a, $b) = each %{ $x{a} } ) {
> print "\tA = '$a', B = '$b'\n";
> }

WTF!

Must of course read ($_ instead of 'a'):
...
while ( my ($a, $b) = each %{ $x{$_} } ) {
...

Sorry

M.

Re: perl inbuilt function "each" may be having a bug

am 20.08.2007 12:59:59 von Tad McClellan

al.moorthi@gmail.com wrote:

> This code is not working


It is doing exactly what it is supposed to do.

If you want us to help you modify it to do something else,
then you need to share what it is that you want it to do instead.


> and assigning values to '' , actually it
> shouldn't.
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> my %x= (a=>{a=>1,b=>2}, c=>3);
> foreach (0..3) {
> my($a,$b) = each %{$x{a}};
> print "A = '$a', B = '$b'\n";
> }
> exit(0);
>
> perl each-bug.pl
> OUTPUT IS:
> A = 'a', B = '1'
> A = 'b', B = '2'


Normal output so far.


> Use of uninitialized value in concatenation (.) or string at each-
> bug.pl line 8.
> Use of uninitialized value in concatenation (.) or string at each-
> bug.pl line 8.
> A = '', B = ''


From "perldoc -f each":

When the hash is entirely read, a null array is returned in list context
...

> A = 'a', B = '1'

... The next call to C after that will start iterating again.


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"