Why doesn't Perl for () go through all the elements in my array?

Have a perl brain-teaser:

my @l = ('a', 'b', 'c');
for (@l) {
    my $n = 1;
    print shift @l while (@l and $n --> 0);
    print "\n";
}

What is he typing? Must be a, b and c, right? But oh wait, there is an error somewhere, it only prints the letters a and b. Probably just some kind of stupidity one by one, it should be easy to solve, right?

So do a little code change to check everything and change @l to

my @l = ('a', 'b', 'c', 'd');

What is he typing? Probably a, b and c are stupid from one because of this, right? ... Wait a second, in fact it still only prints a and b. Okay, so the mistake is that it only prints the first two characters.

Change @l to again

my @l = ('a', 'b', 'c', 'd', 'e');

Uhm, a, b c. d e. , 2 , , . , f, a, b c, f g, a, b, c d.

$n.

, ?

+3
3

, - . , -. , ( , ) Perl , :

for ( @l ) { 
    #...
}

:

for ( my $i = 0; $i < @l; $i++ ) { 
    local $_ = $l[$i];
    #...
}    

, @l ( 'c' ), , scalar( @l ), . , .

, . , - , , .

use strict;
use warnings;
use English qw<$LIST_SEPARATOR>;
use Test::More 'no_plan';

sub test_loops_without_shifts { 
    my @l = @_;
    my @tests;
    for ( @l ) { 
        push @tests, $_;
    }
    my @l2 = @_;
    my $n  = @tests;
    my $i = 0;
    for ( $i = 0; $i < @l2; $i++ ) { 
        local $_ = $l2[$i];
        my $x = shift @tests;
        my $g = $_;
        is( $g, $x, "expected: $x, got: $g" );
    }
    is( $n, $i );
    is_deeply( \@l, \@l2, do { local $LIST_SEPARATOR = .', '; "leftover: ( @l ) = ( @l2 )" } );
    return $i;
}

sub test_loops { 
    my @l = @_;
    my @tests;
    for ( @l ) { 
        push @tests, shift @l;
    }
    my @l2 = @_;
    my $n  = @tests;
    my $i = 0;
    for ( $i = 0; $i < @l2; $i++ ) { 
        local $_ = $l2[$i];
        my $x = shift @tests;
        my $g = shift @l2;
        is( $g, $x, "expected: $x, got: $g" );
    }
    is( $n, $i );
    is_deeply( \@l, \@l2, do { local $LIST_SEPARATOR = ', 'c; "leftover: ( @l ) = ( @l2 )" } );
    return $i;
}

is( test_loops( 'a'..'c' ), 2 );
is( test_loops( 'a'..'d' ), 2 );
is( test_loops( 'a'..'e' ), 3 );
is( test_loops( 'a'..'f' ), 3 );
is( test_loops( 'a'..'g' ), 4 );
is( test_loops_without_shifts( 'a'..'c' ), 3 );
is( test_loops_without_shifts( 'a'..'d' ), 4 );
is( test_loops_without_shifts( 'a'..'e' ), 5 );
is( test_loops_without_shifts( 'a'..'f' ), 6 );
is( test_loops_without_shifts( 'a'..'g' ), 7 );
+1

, perldoc perlsyn , :

- LIST , foreach , , , splice. .

, foreach foreach LIST, LIST, . , foreach for .

+15

What happens while you are using forand shift. This way you iterate over the list, changing it, not a good idea.

+14
source

Source: https://habr.com/ru/post/1727513/


All Articles