Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Perl-Critic CPAN distribution.

Report information
The Basics
Id: 42791
Status: resolved
Priority: 0/
Queue: Perl-Critic

People
Owner: Nobody in particular
Requestors: hinrik.sig [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: ProhibitFixedStringMatches should make an exception for alternations
I think the RegularExpressions::ProhibitFixedStringMatches policy should not complain when the regex in question contains an alternation. It's much nicer to write "if ($var =~ /^(foo|bar|baz|quux)$/)" rather than "if ($var eq 'foo' || $var eq 'bar' || $var eq 'baz' || $var eq 'quux')".
On Mon Jan 26 03:55:45 2009, HINRIK wrote: Show quoted text
> I think the RegularExpressions::ProhibitFixedStringMatches policy should > not complain when the regex in question contains an alternation. > > It's much nicer to write "if ($var =~ /^(foo|bar|baz|quux)$/)" rather > than "if ($var eq 'foo' || $var eq 'bar' || $var eq 'baz' || $var eq > 'quux')".
This is actually exactly what this policy is written to prohibit. If you want to silence complaints from this policy, you can disable it in your perlcriticrc file. [-RegularExpressions::ProhibitFixedStringMatches]
Could you explain the rationale behind this policy? Take some code like if (/\A(X|Y)\z/ or /\Aaaa(X|Y)\z/) { say "letter is $1"; } (adapted from a real-world example). Rewriting this to use 'eq' comparisons would make it less clear. Could the use of capturing parentheses be a mitigating factor for whatever bad practice the policy is meant to prevent?
Subject: Re: [rt.cpan.org #42791] ProhibitFixedStringMatches should make an exception for alternations
Date: Mon, 16 Mar 2009 19:54:46 -0500
To: bug-Perl-Critic [...] rt.cpan.org
From: Elliot Shank <perl [...] galumph.com>
EDAVIS via RT wrote: Show quoted text
> Could you explain the rationale behind this policy? > > Take some code like > > if (/\A(X|Y)\z/ or /\Aaaa(X|Y)\z/) { > say "letter is $1"; > } > > (adapted from a real-world example). Rewriting this to use 'eq' > comparisons would make it less clear. > > Could the use of capturing parentheses be a mitigating factor for > whatever bad practice the policy is meant to prevent?
The suggestion is not to use eq, but character classes, i.e. if (/\A([XY])\z/ or /\Aaaa([XY])\z/) { say "letter is $1"; }
Show quoted text
>>if (/\A(X|Y)\z/ or /\Aaaa(X|Y)\z/) { >> say "letter is $1"; >>}
Show quoted text
>The suggestion is not to use eq, but character classes,
Sorry I gave an oversimplified example. I meant something more like if (/\A(foo|bar)\z/ or /\Afred:(foo|baz)\z/) { say "got $1"; } else { die "malformed line: $_"; } Currently perlcritic would have that rewritten with a mixture of 'eq' and regexp tests, which would be less clear.
Subject: Re: [rt.cpan.org #42791] ProhibitFixedStringMatches should make an exception for alternations
Date: Sun, 05 Apr 2009 22:20:01 -0500
To: bug-Perl-Critic [...] rt.cpan.org
From: Elliot Shank <perl [...] galumph.com>
EDAVIS via RT wrote: Show quoted text
> Sorry I gave an oversimplified example. I meant something more like > > if (/\A(foo|bar)\z/ or /\Afred:(foo|baz)\z/) { > say "got $1"; > } > else { > die "malformed line: $_"; > } > > Currently perlcritic would have that rewritten with a mixture of 'eq' > and regexp tests, which would be less clear.
In terms of just the condition, I think if ($_ eq 'foo' or $_ eq 'bar' or /\Afred:(foo|baz)\z/) { ... } is actually clearer. On the other hand, the equivalence tests do make the real code more verbose: if ($_ eq 'foo' or $_ eq 'bar') { say "got $_"; } elsif (/\Afred:(foo|baz)\z/) { say "got $1"; } else { die "malformed line: $_"; } which may be considered to be more complicated. The equivalent if (/\A(?:fred:)?(foo|baz)\z/) { say "got $1"; } else { die "malformed line: $_"; } shouldn't trip it. But the simple case you originally gave is really what the policy is targeting. And if you've got a large set of potential cases, you should really be using a hash lookup, rather than a set of equivalence tests. In your more complicated example, the larger scope is what makes the code simpler in your approach. But this policy doesn't look at the larger scope, it simply looks at the regex. Yes, this is a limitation, but, given that, the policy is doing precisely what it is supposed to do.
OK, thanks for the clarification. If the policy really is intended to forbid use of regular expressions that match the whole string using alternation (foo|bar) but not other regexp features, then I will simply turn it off. However, I feel the policy is misnamed (it prohibits more than just fixed string matches), and it would still be useful to have a policy that prohibits fixed string matches. Most Perl programmers would agree that $str =~ /\Ahello\z/ is a bad idea, but forbidding /\Ahello (there|everybody)\z/, particularly when the code wants to use the value captured in $1, is more controversial and not everyone will want it. So I would suggest adding a more basic policy that forbids fixed string matches (but allows alternation and other regexp features), which could be added with severity 3 or 4. Meanwhile this policy would better be named ProhibitWholeStringRegexpsUsingOnlyAlternation (or something like that) and should probably be moved to --brutal severity.
Subject: Re: [rt.cpan.org #42791] ProhibitFixedStringMatches should make an exception for alternations
Date: Mon, 06 Apr 2009 10:39:49 -0500
To: bug-Perl-Critic [...] rt.cpan.org
From: Elliot Shank <perl [...] galumph.com>
EDAVIS via RT wrote: Show quoted text
> is a bad idea, but forbidding /\Ahello (there|everybody)\z/, > particularly when the code wants to use the value captured in $1, is > more controversial and not everyone will want it.
That is not what the policy does. It does not complain about that regex. It will, however, complain about /\A(there|everybody)\z/. And, in the case of your more complicated example, I gave you a way to reformulate the condition so that the policy won't complain.
Show quoted text
>It does not complain about that >regex. It will, however, complain about /\A(there|everybody)\z/.
Sorry for misunderstanding. I think the policy is a bit misnamed - ProhibitAlternationOnlyStringMatches might be better, perhaps with a separate ProhibitFixedStringMatches policy for regexps that really are /\Afoo\z/ with no fancy regexp features at all. But this ticket in the end boils down to a disagreement about best practice, so you can close it.