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.