line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions; |
2
|
|
|
|
|
|
|
|
3
|
40
|
|
|
40
|
|
28720
|
use 5.010001; |
|
40
|
|
|
|
|
206
|
|
4
|
40
|
|
|
40
|
|
288
|
use strict; |
|
40
|
|
|
|
|
121
|
|
|
40
|
|
|
|
|
948
|
|
5
|
40
|
|
|
40
|
|
255
|
use warnings; |
|
40
|
|
|
|
|
101
|
|
|
40
|
|
|
|
|
1062
|
|
6
|
40
|
|
|
40
|
|
221
|
use Readonly; |
|
40
|
|
|
|
|
148
|
|
|
40
|
|
|
|
|
2270
|
|
7
|
|
|
|
|
|
|
|
8
|
40
|
|
|
40
|
|
306
|
use List::SomeUtils qw( any none ); |
|
40
|
|
|
|
|
134
|
|
|
40
|
|
|
|
|
2545
|
|
9
|
|
|
|
|
|
|
|
10
|
40
|
|
|
|
|
2308
|
use Perl::Critic::Utils qw{ |
11
|
|
|
|
|
|
|
:booleans :characters :severities :data_conversion :classification :ppi |
12
|
40
|
|
|
40
|
|
339
|
}; |
|
40
|
|
|
|
|
154
|
|
13
|
|
|
|
|
|
|
|
14
|
40
|
|
|
40
|
|
24921
|
use parent 'Perl::Critic::Policy'; |
|
40
|
|
|
|
|
118
|
|
|
40
|
|
|
|
|
267
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = '1.146'; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Readonly::Array my @BUILTIN_LIST_FUNCS => qw( map grep ); |
21
|
|
|
|
|
|
|
Readonly::Array my @CPAN_LIST_FUNCS => _get_cpan_list_funcs(); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub _get_cpan_list_funcs { |
26
|
|
|
|
|
|
|
return qw( List::Util::first ), |
27
|
40
|
|
|
40
|
|
170
|
map { ('List::MoreUtils::'.$_, 'List::SomeUtils::'.$_) } _get_list_moreutils_funcs(); |
|
480
|
|
|
|
|
1494
|
|
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub _get_list_moreutils_funcs { |
33
|
40
|
|
|
40
|
|
167
|
return qw(any all none notall true false firstidx first_index |
34
|
|
|
|
|
|
|
lastidx last_index insert_after insert_after_string); |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub _is_topic { |
40
|
220
|
|
|
220
|
|
348
|
my $elem = shift; |
41
|
220
|
|
66
|
|
|
1408
|
return defined $elem |
42
|
|
|
|
|
|
|
&& $elem->isa('PPI::Token::Magic') |
43
|
|
|
|
|
|
|
&& $elem->content() eq q{$_}; ##no critic (InterpolationOfMetachars) |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
Readonly::Scalar my $DESC => q{Don't modify $_ in list functions}; ##no critic (InterpolationOfMetachars) |
50
|
|
|
|
|
|
|
Readonly::Scalar my $EXPL => [ 114 ]; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub supported_parameters { |
55
|
|
|
|
|
|
|
return ( |
56
|
|
|
|
|
|
|
{ |
57
|
107
|
|
|
107
|
0
|
2188
|
name => 'list_funcs', |
58
|
|
|
|
|
|
|
description => 'The base set of functions to check.', |
59
|
|
|
|
|
|
|
default_string => join ($SPACE, @BUILTIN_LIST_FUNCS, @CPAN_LIST_FUNCS ), |
60
|
|
|
|
|
|
|
behavior => 'string list', |
61
|
|
|
|
|
|
|
}, |
62
|
|
|
|
|
|
|
{ |
63
|
|
|
|
|
|
|
name => 'add_list_funcs', |
64
|
|
|
|
|
|
|
description => 'The set of functions to check, in addition to those given in list_funcs.', |
65
|
|
|
|
|
|
|
default_string => $EMPTY, |
66
|
|
|
|
|
|
|
behavior => 'string list', |
67
|
|
|
|
|
|
|
}, |
68
|
|
|
|
|
|
|
); |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
122
|
|
|
122
|
1
|
473
|
sub default_severity { return $SEVERITY_HIGHEST } |
72
|
92
|
|
|
92
|
1
|
389
|
sub default_themes { return qw(core bugs pbp certrule ) } |
73
|
52
|
|
|
52
|
1
|
162
|
sub applies_to { return 'PPI::Token::Word' } |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub initialize_if_enabled { |
78
|
87
|
|
|
87
|
1
|
330
|
my ($self, $config) = @_; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
$self->{_all_list_funcs} = { |
81
|
87
|
|
|
|
|
235
|
hashify keys %{ $self->{_list_funcs} }, keys %{ $self->{_add_list_funcs} } |
|
87
|
|
|
|
|
1208
|
|
|
87
|
|
|
|
|
488
|
|
82
|
|
|
|
|
|
|
}; |
83
|
|
|
|
|
|
|
|
84
|
87
|
|
|
|
|
652
|
return $TRUE; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub violates { |
90
|
469
|
|
|
469
|
1
|
1042
|
my ($self, $elem, $doc) = @_; |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# Is this element a list function? |
93
|
469
|
100
|
|
|
|
1169
|
return if not $self->{_all_list_funcs}->{$elem}; |
94
|
84
|
100
|
|
|
|
574
|
return if not is_function_call($elem); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# Only the block form of list functions can be analyzed. |
97
|
81
|
50
|
|
|
|
260
|
return if not my $first_arg = first_arg( $elem ); |
98
|
81
|
50
|
|
|
|
282
|
return if not $first_arg->isa('PPI::Structure::Block'); |
99
|
81
|
100
|
|
|
|
242
|
return if not $self->_has_topic_side_effect( $first_arg, $doc ); |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Must be a violation |
102
|
48
|
|
|
|
|
431
|
return $self->violation( $DESC, $EXPL, $elem ); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub _has_topic_side_effect { |
108
|
81
|
|
|
81
|
|
232
|
my ( $self, $node, $doc ) = @_; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# Search through all significant elements in the block, |
111
|
|
|
|
|
|
|
# testing each element to see if it mutates the topic. |
112
|
81
|
|
50
|
|
|
246
|
my $tokens = $node->find( 'PPI::Token' ) || []; |
113
|
81
|
|
|
|
|
25121
|
for my $elem ( @{ $tokens } ) { |
|
81
|
|
|
|
|
242
|
|
114
|
319
|
100
|
|
|
|
1342
|
next if not $elem->significant(); |
115
|
204
|
100
|
|
|
|
424
|
return 1 if _is_assignment_to_topic( $elem ); |
116
|
195
|
100
|
|
|
|
461
|
return 1 if $self->_is_topic_mutating_regex( $elem, $doc ); |
117
|
162
|
100
|
|
|
|
358
|
return 1 if _is_topic_mutating_func( $elem ); |
118
|
157
|
100
|
|
|
|
412
|
return 1 if _is_topic_mutating_substr( $elem ); |
119
|
|
|
|
|
|
|
} |
120
|
33
|
|
|
|
|
306
|
return; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub _is_assignment_to_topic { |
126
|
204
|
|
|
204
|
|
331
|
my $elem = shift; |
127
|
204
|
100
|
|
|
|
398
|
return if not _is_topic( $elem ); |
128
|
|
|
|
|
|
|
|
129
|
32
|
|
|
|
|
275
|
my $sib = $elem->snext_sibling(); |
130
|
32
|
100
|
100
|
|
|
878
|
if ($sib && $sib->isa('PPI::Token::Operator')) { |
131
|
27
|
100
|
|
|
|
87
|
return 1 if _is_assignment_operator( $sib ); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
25
|
|
|
|
|
173
|
my $psib = $elem->sprevious_sibling(); |
135
|
25
|
100
|
66
|
|
|
489
|
if ($psib && $psib->isa('PPI::Token::Operator')) { |
136
|
3
|
100
|
|
|
|
12
|
return 1 if _is_increment_operator( $psib ); |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
23
|
|
|
|
|
71
|
return; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub _is_topic_mutating_regex { |
145
|
195
|
|
|
195
|
|
404
|
my ( $self, $elem, $doc ) = @_; |
146
|
195
|
100
|
100
|
|
|
1109
|
return if ! ( $elem->isa('PPI::Token::Regexp::Substitute') |
147
|
|
|
|
|
|
|
|| $elem->isa('PPI::Token::Regexp::Transliterate') ); |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# Exempt PPI::Token::Regexp::Transliterate objects IF the replacement |
150
|
|
|
|
|
|
|
# string is empty AND neither the /d or /s flags are specified, OR the |
151
|
|
|
|
|
|
|
# replacement string equals the match string AND neither the /c or /s |
152
|
|
|
|
|
|
|
# flags are specified. RT 44515. |
153
|
|
|
|
|
|
|
# |
154
|
|
|
|
|
|
|
# NOTE that, at least as of 5.14.2, tr/// does _not_ participate in the |
155
|
|
|
|
|
|
|
# 'use re /modifiers' mechanism. And a good thing, too, since the |
156
|
|
|
|
|
|
|
# modifiers that _are_ common (/s and /d) mean something completely |
157
|
|
|
|
|
|
|
# different in tr///. |
158
|
60
|
100
|
|
|
|
196
|
if ( $elem->isa( 'PPI::Token::Regexp::Transliterate') ) { |
159
|
56
|
|
|
|
|
173
|
my $subs = $elem->get_substitute_string(); |
160
|
56
|
|
|
|
|
1053
|
my %mods = $elem->get_modifiers(); |
161
|
56
|
100
|
|
|
|
758
|
$mods{r} and return; # Introduced in Perl 5.13.7 |
162
|
54
|
100
|
|
|
|
171
|
if ( $EMPTY eq $subs ) { |
|
|
100
|
|
|
|
|
|
163
|
24
|
100
|
100
|
|
|
132
|
$mods{d} or $mods{s} or return; |
164
|
|
|
|
|
|
|
} elsif ( $elem->get_match_string() eq $subs ) { |
165
|
24
|
100
|
100
|
|
|
410
|
$mods{c} or $mods{s} or return; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# As of 5.13.2, the substitute built-in supports the /r modifier, which |
170
|
|
|
|
|
|
|
# causes the operation to return the modified string and leave the |
171
|
|
|
|
|
|
|
# original unmodified. This does not parse under earlier Perls, so there |
172
|
|
|
|
|
|
|
# is no version check. |
173
|
|
|
|
|
|
|
|
174
|
34
|
100
|
|
|
|
218
|
if ( $elem->isa( 'PPI::Token::Regexp::Substitute' ) ) { |
175
|
4
|
50
|
|
|
|
19
|
my $re = $doc->ppix_regexp_from_element( $elem ) |
176
|
|
|
|
|
|
|
or return; |
177
|
4
|
100
|
|
|
|
14290
|
$re->modifier_asserted( 'r' ) |
178
|
|
|
|
|
|
|
and return; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# If the previous sibling does not exist, then |
182
|
|
|
|
|
|
|
# the regex implicitly binds to $_ |
183
|
33
|
|
|
|
|
203
|
my $prevsib = $elem->sprevious_sibling; |
184
|
33
|
100
|
|
|
|
947
|
return 1 if not $prevsib; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# If the previous sibling does exist, then it |
187
|
|
|
|
|
|
|
# should be a binding operator. |
188
|
22
|
100
|
|
|
|
57
|
return 1 if not _is_binding_operator( $prevsib ); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# Check if the sibling before the biding operator |
191
|
|
|
|
|
|
|
# is explicitly set to $_ |
192
|
11
|
|
|
|
|
78
|
my $bound_to = $prevsib->sprevious_sibling; |
193
|
11
|
|
|
|
|
240
|
return _is_topic( $bound_to ); |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub _is_topic_mutating_func { |
199
|
162
|
|
|
162
|
|
287
|
my $elem = shift; |
200
|
162
|
100
|
|
|
|
663
|
return if not $elem->isa('PPI::Token::Word'); |
201
|
28
|
|
|
|
|
89
|
my @mutator_funcs = qw(chop chomp undef); |
202
|
28
|
100
|
|
77
|
|
147
|
return if not any { $elem->content() eq $_ } @mutator_funcs; |
|
77
|
|
|
|
|
312
|
|
203
|
7
|
50
|
|
|
|
61
|
return if not is_function_call( $elem ); |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# If these functions have no argument, |
206
|
|
|
|
|
|
|
# they default to mutating $_ |
207
|
7
|
|
|
|
|
21
|
my $first_arg = first_arg( $elem ); |
208
|
7
|
100
|
|
|
|
23
|
if (not defined $first_arg) { |
209
|
|
|
|
|
|
|
# undef does not default to $_, unlike the others |
210
|
3
|
100
|
|
|
|
12
|
return if $elem->content() eq 'undef'; |
211
|
2
|
|
|
|
|
21
|
return 1; |
212
|
|
|
|
|
|
|
} |
213
|
4
|
|
|
|
|
11
|
return _is_topic( $first_arg ); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Readonly::Scalar my $MUTATING_SUBSTR_ARG_COUNT => 4; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub _is_topic_mutating_substr { |
221
|
157
|
|
|
157
|
|
264
|
my $elem = shift; |
222
|
157
|
100
|
|
|
|
357
|
return if $elem->content() ne 'substr'; |
223
|
1
|
50
|
|
|
|
9
|
return if not is_function_call( $elem ); |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# check and see if the first arg is $_ |
226
|
1
|
|
|
|
|
7
|
my @args = parse_arg_list( $elem ); |
227
|
1
|
|
33
|
|
|
9
|
return @args >= $MUTATING_SUBSTR_ARG_COUNT && _is_topic( $args[0]->[0] ); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
{ |
233
|
|
|
|
|
|
|
##no critic(ArgUnpacking) |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
my %assignment_ops = hashify qw( |
236
|
|
|
|
|
|
|
= *= /= += -= %= **= x= .= &= |= ^= &&= ||= <<= >>= //= ++ -- |
237
|
|
|
|
|
|
|
); |
238
|
27
|
|
|
27
|
|
94
|
sub _is_assignment_operator { return exists $assignment_ops{$_[0]} } |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
my %increment_ops = hashify qw( ++ -- ); |
241
|
3
|
|
|
3
|
|
9
|
sub _is_increment_operator { return exists $increment_ops{$_[0]} } |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
my %binding_ops = hashify qw( =~ !~ ); |
244
|
22
|
|
|
22
|
|
61
|
sub _is_binding_operator { return exists $binding_ops{$_[0]} } |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
1; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
__END__ |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=pod |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=head1 NAME |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions - Don't modify C<$_> in list functions. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=head1 AFFILIATION |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
This Policy is part of the core L<Perl::Critic|Perl::Critic> |
263
|
|
|
|
|
|
|
distribution. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head1 DESCRIPTION |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
C<map>, C<grep> and other list operators are intended to transform |
269
|
|
|
|
|
|
|
arrays into other arrays by applying code to the array elements one by |
270
|
|
|
|
|
|
|
one. For speed, the elements are referenced via a C<$_> alias rather |
271
|
|
|
|
|
|
|
than copying them. As a consequence, if the code block of the C<map> |
272
|
|
|
|
|
|
|
or C<grep> modify C<$_> in any way, then it is actually modifying the |
273
|
|
|
|
|
|
|
source array. This IS technically allowed, but those side effects can |
274
|
|
|
|
|
|
|
be quite surprising, especially when the array being passed is C<@_> |
275
|
|
|
|
|
|
|
or perhaps C<values(%ENV)>! Instead authors should restrict in-place |
276
|
|
|
|
|
|
|
array modification to C<for(@array) { ... }> constructs instead, or |
277
|
|
|
|
|
|
|
use C<List::SomeUtiles:apply()> or C<List::MoreUtils::apply()>. |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=head1 CONFIGURATION |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
By default, this policy applies to the following list functions: |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
map grep |
284
|
|
|
|
|
|
|
List::Util qw(first) |
285
|
|
|
|
|
|
|
List::MoreUtils qw(any all none notall true false firstidx |
286
|
|
|
|
|
|
|
first_index lastidx last_index insert_after |
287
|
|
|
|
|
|
|
insert_after_string) |
288
|
|
|
|
|
|
|
List::SomeUtils qw(any all none notall true false firstidx |
289
|
|
|
|
|
|
|
first_index lastidx last_index insert_after |
290
|
|
|
|
|
|
|
insert_after_string) |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
This list can be overridden the F<.perlcriticrc> file like this: |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
[ControlStructures::ProhibitMutatingListFunctions] |
295
|
|
|
|
|
|
|
list_funcs = map grep List::Util::first |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Or, one can just append to the list like so: |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
[ControlStructures::ProhibitMutatingListFunctions] |
300
|
|
|
|
|
|
|
add_list_funcs = Foo::Bar::listmunge |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=head1 LIMITATIONS |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
This policy deliberately does not apply to C<for (@array) { ... }> or |
305
|
|
|
|
|
|
|
C<List::MoreUtils::apply()> C<List::SomeUtils::apply()>. |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
Currently, the policy only detects explicit external module usage like |
308
|
|
|
|
|
|
|
this: |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
my @out = List::MoreUtils::any {s/^foo//} @in; |
311
|
|
|
|
|
|
|
my @out = List::SomeUtils::any {s/^foo//} @in; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
and not like this: |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
use List::MoreUtils qw(any); |
316
|
|
|
|
|
|
|
my @out = any {s/^foo//} @in; |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
use List::SomeUtils qw(any); |
319
|
|
|
|
|
|
|
my @out = any {s/^foo//} @in; |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
This policy looks only for modifications of C<$_>. Other naughtiness |
322
|
|
|
|
|
|
|
could include modifying C<$a> and C<$b> in C<sort> and the like. |
323
|
|
|
|
|
|
|
That's beyond the scope of this policy. |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=head1 SEE ALSO |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
There is discussion of this policy at |
329
|
|
|
|
|
|
|
L<http://perlmonks.org/index.pl?node_id=743445>. |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head1 AUTHOR |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
Chris Dolan <cdolan@cpan.org> |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
Michael Wolf <MichaelRWolf@att.net> |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=head1 COPYRIGHT |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
Copyright (c) 2006-2021 Chris Dolan. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
344
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=cut |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# Local Variables: |
349
|
|
|
|
|
|
|
# mode: cperl |
350
|
|
|
|
|
|
|
# cperl-indent-level: 4 |
351
|
|
|
|
|
|
|
# fill-column: 78 |
352
|
|
|
|
|
|
|
# indent-tabs-mode: nil |
353
|
|
|
|
|
|
|
# End: |
354
|
|
|
|
|
|
|
# ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround : |
355
|
|
|
|
|
|
|
|