Home > other >  PerlCritic example: loop iterator is not lexical
PerlCritic example: loop iterator is not lexical

Time:12-15

When debugging some older perl code I use perl critic as a way to spot bugs. I stumble across this 'Loop iterator is not lexical' policy often: Perl::Critic::Policy::Variables::RequireLexicalLoopIterators And its never been a bug. When I implement the authors example in a test program, I dont seem to reproduce the problem it attempts to solve:

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

my $bicycle = {is_red => 1, has_baseball_card_in_spokes => 1, has_bent_kickstand => 1, locked => 1};

my $bicycle1 = {is_green => 1, has_baseball_card_in_spokes => 1, has_bent_kickstand => 1, locked => 1};

my $bicycle2 = {is_blue => 1, has_baseball_card_in_spokes => 0, has_bent_kickstand => 0, locked => 1};

my @things_attached_to_the_bike_rack = ($bicycle,$bicycle1,$bicycle2);

for $bicycle (@things_attached_to_the_bike_rack) {
    if (
            $bicycle->{is_red}
        and $bicycle->{has_baseball_card_in_spokes}
        and $bicycle->{has_bent_kickstand}
    ) {
        $bicycle->{locked} = 0;

        last;
    }
}

if ( $bicycle and !$bicycle->{locked} ) {
    print "riding home in time for dinner\n";
}

Admittedly I did not make a blessed object with functions, but a hash reference instead, so perhaps it has something to do with objects in Perl. Even if I re-arrange the order of the array I do arrive home in time for dinner every time. So I must be missing something obvious, and I'd like a reproducible example to show the case when this is a problem.

I realize there are old questions about this, but I was wondering if this was still a relevant policy in late 2021.

CodePudding user response:

Your code is different from the policy example. Your code assigns a value to $bicycle outside the loop, whereas the policy example does not.

The following is code that more closely represents the intention of the policy example:

use strict;
use warnings;
use diagnostics;

my $bicycle0 = {is_red => 1, has_baseball_card_in_spokes => 1, has_bent_kickstand => 1, locked => 1};
my $bicycle1 = {is_green => 1, has_baseball_card_in_spokes => 1, has_bent_kickstand => 1, locked => 1};
my $bicycle2 = {is_blue => 1, has_baseball_card_in_spokes => 0, has_bent_kickstand => 0, locked => 1};

my @things_attached_to_the_bike_rack = ($bicycle0, $bicycle1, $bicycle2);

my $bicycle;
for $bicycle (@things_attached_to_the_bike_rack) {
    if (
            $bicycle->{is_red}
        and $bicycle->{has_baseball_card_in_spokes}
        and $bicycle->{has_bent_kickstand}
    ) {
        $bicycle->{locked} = 0;

        last;
    }
}

if ( $bicycle and !$bicycle->{locked} ) {
    print "riding home in time for dinner\n";
}

When I run this, I do not see the riding home in time for dinner message, as expected, like I do when I run your original code.

  •  Tags:  
  • perl
  • Related