1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cat label.pl
use v5.24;
use strict;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
MARKE:
for my $i ( 1 .. 10) {
next Marke if $i == 5;
say "$i ist nicht fünf";
}
$ perl label.pl
1 ist nicht fünf
2 ist nicht fünf
3 ist nicht fünf
4 ist nicht fünf
Label not found for "next Marke" at label.pl line 9.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use v5.24;
use strict;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
for my $i ( 1 .. 10) {
{
my $var = 'asdf';
# tut was mit $Var
next if $i == 5;
}
say "$i ist nicht fünf";
}
2023-12-15T14:51:47 barneyIch füge gern mal einfache Blöcke in meinem Code ein, damit der Sichtbarkeitsbereich von lexikalischen Variablen klein bleibt.
1 2 3 4 5 6 7 8 9 10 11 12
for my $i ( 1 .. 10) { my $var = 'a'.$i; say "aussen oben: $var"; if (1) { my $var = 'asdf'.$i; say "innen: $var"; # tut was mit $Var next if $i == 5; } say "aussen unten immernoch: $var"; say "$i ist nicht fuenf"; }
2023-12-16T10:37:10 hajDas if (1) würde ich aber weglassen, das lenkt nur ab.
2023-12-16T15:07:12 hajOk, das next habe ich nicht beachtet. Aber eben deswegen gibt's ja die Regel, Labels zu verwenden... Ein Label bei der Schleife und bei next gefällt mir besser als ein if (1).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use v5.24;
use strict;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
for my $i ( 1 .. 10) {
say "$i ist ", eval {
my $int = 5;
my $str = 'fünf';
return "kleiner $str" if $i < $int;
return "gleich $str" if $i == $int;
return "größer $str";
};
}
1 2 3 4 5 6
for my $i ( 1 .. 10) { say "$i ist ", eval { next if $i == 5; say $i; }; }
QuoteExiting eval via next at test.pl line xxx.
2023-12-15T07:31:04 barneySCNR: next __PACKAGE__ ist mit dieser Regel erlaubt.Ja, in OTRS/Znuny/OTOBO gibt es dazu die Regel RequireLabel. Diese Regel verlangt aber nur dass Labels verwendet werden sollen. Und dass die Label mit einem ASCII Großbuchstaben anfangen. Ob die Zielmarke definiert ist wird dabei nicht überprüft.
2023-12-15T07:31:04 barneyWenn man es richtig machen will dann braucht man eigentlich nur einen Stapel mit den angetroffenen Label und eine Stapel mit Zählern wie viele Labels es im aktuellen Scope, eval, sub, method, file gibt. Dann kann man beim Verlassen des Bereiches die Stapel wieder abbauen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
package Perl::Critic::Policy::GoodLabels; use strict; use warnings; our $VERSION = 0.01; use 5.032; use Perl::Critic::Utils qw{}; use parent 'Perl::Critic::Policy'; my $description = q{Unknown Label}; my $explanation = <<'UNKNOWN_LABEL'; The label '%s' used as a target of next, last, or redo is not defined in the current scope UNKNOWN_LABEL chomp $explanation; sub supported_parameters { return; } sub default_severity { return $Perl::Critic::Utils::SEVERITY_HIGHEST; } sub applies_to { return 'PPI::Statement::Break' } sub prepare_to_scan_document { my ( $self, $document ) = @_; return 1; } my %allowed_labels; sub violates { my ( $self, $element, $document ) = @_; %allowed_labels or _collect_labels($document); my @children = $element->schildren(); if ( $children[0]->content() ne 'next' && $children[0]->content() ne 'last' && $children[0]->content() ne 'redo' ) { return; } my $label = $children[0]->snext_sibling(); my $content = $label->content; my $found = 0; CANDIDATE: for my $allowed ( @{ $allowed_labels{$content} } ) { if ( $allowed->contains($label) ) { $found = 1; last CANDIDATE; } } if ( !$found ) { return $self->violation( $description, sprintf( $explanation, $content ), $label ); } return; } sub _collect_labels { my ($document) = @_; my $compounds = $document->find(q(Statement::Compound)); for my $compound ( @{$compounds} ) { for my $label ( grep { $_->isa(q(PPI::Token::Label)) } $compound->children ) { my $content = $label->content; $content =~ s/:$//xms; $allowed_labels{$content} //= []; push @{ $allowed_labels{$content} }, $compound; } } return; } 1;