ravi45722 has asked for the wisdom of the Perl Monks concerning the following question:

use strict; use warnings; my $row_element = 0; my $col_element = 0; foreach my $col_element (0 .. $max_cols) { foreach $row_element (0 .. $max_rows) { print $row_element; } } print $row_element;

Here in the foreach loop I am changing the value of  $row_element. Still its printing zero out of the loop. Why??? I am maintaining scope by initialising at top.

Replies are listed 'Best First'.
Re: Variable in a foreach loop
by haukex (Archbishop) on Jul 14, 2016 at 10:50 UTC
Re: Variable in a foreach loop
by hippo (Archbishop) on Jul 14, 2016 at 11:28 UTC

    That isn't the code you are running because it won't even compile.

    $ perl 1167769.pl Global symbol "$max_cols" requires explicit package name at 1167769.pl + line 8. Global symbol "$max_rows" requires explicit package name at 1167769.pl + line 10. Execution of 1167769.pl aborted due to compilation errors.
Re: Variable in a foreach loop
by perldigious (Priest) on Jul 14, 2016 at 12:50 UTC

    Can you show your complete code that your are attempting to run? I see no declaration or initialization for $max_cols or $max_rows. Assuming they exist elsewhere, this code would just print out the numbers 0 to whatever is in $max_rows a number of times equal to $max_cols+1 and then print the value of $max_rows one additional time.

    EDIT: Ah, I think I see the behavior you are trying to illustrate. The last print actually doesn't get the last value ($max_rows) of the inner foreach loop despite the omission of my, it gets the original value scoped outside the loop (I added declarations and initializations).

    use strict; use warnings; my $max_cols = 3; my $max_rows = 3; my $row_element = 0; my $col_element = 0; foreach my $col_element (0 .. $max_cols) { foreach $row_element (0 .. $max_rows) { print $row_element; } } print $row_element;

    This isn't what I would have expected (obviously from my original post) either, but as haukex pointed out it does appear to be the intended behavior. I've never tried using a foreach loop without my. I guess you would be stuck doing something like this if you wanted the original scalar outside the foreach loop to update.

    use strict; use warnings; my $max_cols = 3; my $max_rows = 3; my $row_element = 0; my $col_element = 0; foreach my $col_element (0 .. $max_cols) { foreach my $row_element_a (0 .. $max_rows) { $row_element = $row_element_a; print $row_element; } } print $row_element;

    I love it when things get difficult; after all, difficult pays the mortgage. - Dr. Keith Whites
    I hate it when things get difficult, so I'll just sell my house and rent cheap instead. - perldigious

      Hi perldigious,

      ... and then print the value of $max_rows one additional time.

      ravi45722 is correct that the final print prints "0" - see my reply as to why.

      use strict; use warnings; my $max_cols = 2; my $max_rows = 3; my $row_element = 0; foreach my $col_element (0 .. $max_cols) { foreach $row_element (0 .. $max_rows) { print "$row_element\n"; } } print "Last: $row_element\n"; __END__ 0 1 2 3 0 1 2 3 0 1 2 3 Last: 0

      Regards,
      -- Hauke D

        Thanks haukex, I got there eventually, I just had to tweak the code so it would run to see that behavior and understand what ravi45722 was trying to point out. I would have been confused too if I had tried that and not dug through the foreach documentation, I always use my and explicitly update variables at a higher scope with assignments inside the loop body, so I've never seen this behavior before.

        I love it when things get difficult; after all, difficult pays the mortgage. - Dr. Keith Whites
        I hate it when things get difficult, so I'll just sell my house and rent cheap instead. - perldigious
Re: Variable in a foreach loop
by shadowsong (Pilgrim) on Jul 15, 2016 at 11:12 UTC

    Hi ravi45722

    Just to set you straight - that's what it's supposed to do...

    There's a very subtle difference between declaring your iterator inside and outside the loop.

    • If you declare your iterator outside the loop, any value it had will then be restored afterwards
    • If you declare your iterator within the loop a new variable will be created that will exist only within the scope of the loop

    My advice would be rename your iterator variables to avoid confusion with lexicals outside your loops...

    Cheers,
    Shadowsong

Re: Variable in a foreach loop
by InfiniteSilence (Curate) on Jul 16, 2016 at 18:03 UTC

    Having to know how many rows and columns there are in a multi-dimensioned array can become tedious. Unless strictly necessary you can avoid it having to code it into your program...

    use strict; sub dataSetup { return ( [ qw|a b c d| ] , [ qw|a b c d| ] , [ qw|a b c d| ] ) ; } sub main { my @multi = dataSetup(); foreach my $row (@multi){ foreach(@$row){ print qq|$_\n|; } } } #---- &main;

    Celebrate Intellectual Diversity