This started off as a reply to Re: Remove letters from variables used in math operation?, but I decided to turn it into a meditation.

use warnings enables a whole bunch of different warnings. There are four in particular that I think are dumb and have no qualms about disabling when they annoy me:

  1. "uninitialized" - warns about using undef in various situations; e.g. interpolating it into a string, using it in a mathematical expression, etc.

    Why this warning is dumb: undef has well-defined and sensible behaviour when numified or stringified. When this warning is enabled, it forces otherwise good programmers to write:

    my $price = sprintf "%d.%02d", $pounds||0, $pence||0;

    when they should just be writing:

    my $price = sprintf "%d.%02d", $pounds, $pence;

    This warning tends to litter your code with if defined checks making it less readable.

    The argument in favour of it is that sometimes you've got a variable that you expect to be defined, and is not. When you interpolate that into a string, you get a warning. This can help you diagnose hard to track down bugs.

    The counterargument to that is that this warning only comes up if I use undef in a numeric or stringy context, but not in boolean context. If I do want to be warned about unexpected undefs cropping up in my code, why wouldn't I also want to be warned about their use in boolean context?

    i.e. more annoying than useful; and in the cases it is useful, incomplete.

  2. "numeric" - warns about using non-numeric values in numeric contexts.

    Again, sounds a good idea, but incomplete.

    print 'a' + 'b', $/; # warns print [] + {}, $/; # no warning

    Adding together two letters is dumb and probably useless, but adding together an arrayref and a hashref is unquestionably dumber and less useful.

  3. "once" - warns you about using package variables only once, unless you create a lexical alias to them using our.

    When you have strict 'vars', this is rarely any use.

  4. "void" - warns you if you use certain Perl built-in functions in void context (i.e. without doing anything with the value).

    Doesn't cover all built-in functions; doesn't cover functions defined in modules. Just generally inconsistent.

    use v5.12; # behaviour of split changed in 5.12. sub a { split //, 'xyz'; 1 } a(); # warns sub b { split //, 'xyz' } b(); 1; # no warning

    In both cases the result of the split is being ignored.

Now, I don't mean to suggest that use warnings is not useful; it is. Even the four warning categories above can occasionally be useful.

What I am saying is that sometimes particular warnings can be more annoying than they are useful. When that happens, don't jump through hoops to satisfy the warnings pragma. Just disable the warnings which are annoying you.

no warnings 'numeric'; no warnings 'once'; no warnings 'uninitialized'; no warnings 'void';

Strictures and warnings are not a penitence. They're supposed to make your life easier. If they're not doing that, then there is no virtue in suffering them.

Update: (six months later...) now it's time to add "experimental::smartmatch" to that list.

perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'