perl inbuilt function 'each' may be having a bug

Discussion in 'Perl Misc' started by al.moorthi@gmail.com, Aug 20, 2007.

  1. Guest

    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'
    , Aug 20, 2007
    #1
    1. Advertising

  2. Mirco Wahab Guest

    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.
    Mirco Wahab, Aug 20, 2007
    #2
    1. Advertising

  3. 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
    Gunnar Hjalmarsson, Aug 20, 2007
    #3
  4. -berlin.de Guest

    <> 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
    -berlin.de, Aug 20, 2007
    #4
  5. Mirco Wahab Guest

    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.
    Mirco Wahab, Aug 20, 2007
    #5
  6. Mirco Wahab Guest

    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.
    Mirco Wahab, Aug 20, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Raja
    Replies:
    2
    Views:
    14,955
  2. km

    inbuilt function buffer()

    km, Jan 20, 2005, in forum: Python
    Replies:
    0
    Views:
    371
  3. ragav

    Print without using any inbuilt function?

    ragav, Dec 8, 2006, in forum: C Programming
    Replies:
    13
    Views:
    2,030
  4. santosh
    Replies:
    5
    Views:
    886
    Nick Keighley
    Mar 11, 2010
  5. kaushal
    Replies:
    3
    Views:
    182
    Dr J R Stockton
    Aug 11, 2008
Loading...

Share This Page