Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Four annoying warnings

by tobyink (Abbot)
on Dec 09, 2012 at 00:05 UTC ( #1007936=perlmeditation: print w/replies, xml ) Need Help??

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'

Replies are listed 'Best First'.
Re: Four annoying warnings
by BrowserUk (Pope) on Dec 09, 2012 at 00:37 UTC

    Hm. Each of those warnings catch many of my most frequent typos and brain farts in first drafts of code.

    However,I do agree with you that there are many situations where -- at least some of them -- are better ignored than coded around.

    But, your "just disable them" code block makes it look more of a chore than is necessary:

    C:\test>perl -M-warnings=uninitialized,numeric,once,void -E"123;$x=1;p +rint $y; 'A'+0" C:\test>perl -Mwarnings=uninitialized,numeric,once,void -E"123;$x=1;pr +int $y; 'A'+0" Useless use of a constant in void context at -e line 1. Useless use of addition (+) in void context at -e line 1. Name "main::y" used only once: possible typo at -e line 1. Name "main::x" used only once: possible typo at -e line 1. Use of uninitialized value $y in print at -e line 1. Argument "A" isn't numeric in addition (+) at -e line 1.

    (My point being that args to no warnings;can be multiple:no warnings qw[uninitialized numeric once void];

    The one that really bugs me is:

    C:\test>perl -wE"say (1+2)*3" say (...) interpreted as function at -e line 1. Useless use of multiplication (*) in void context at -e line 1. 3

    But it is not the warning that bugs me, but rather the interpretation.

    There is -- IMO -- absolutely no logic for allowing a space between a function name and its argument grouping parens. None whatsoever.

    If the syntax required that if parens are used on a function call, the left paren must be abutted to the function name, that annoyance would go away.

    I also wish that there were a :nocommon group label; though we could probably argue for a week about which should, and should not, be included :)

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    RIP Neil Armstrong

      perl -M-warnings=uninitialized,numeric,once,void -E"123;$x=1;print $y; 'A'+0"

      But with strict that already doesn't compile. When you use strict, "once" usually becomes pretty irrelevant.

      "(My point being that args to no warnings;can be meultiple: no warnings qw[uninitialized numeric once void];"

      I'm aware of that. The four line block of the code was intended as four individual examples of how to disable specific warning categories, rather than a single block that should be copied and pasted into actual scripts.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
        But with strict that already doesn't compile. When you use strict, "once" usually becomes pretty irrelevant.

        Mostly yes, but not if you refer to a fully qualified varable from another package. For example, when I am debugging my code, I often put DB::single=1 at various places. Sometime I leave those line in production code inside assert like error checks, as a kind of assert that will only go off when debugging.

        I have found that those lines will trigger the "once" warning, which is irritating.

Re: Four annoying warnings
by Anonymous Monk on Dec 10, 2012 at 04:18 UTC
    If you did the right thing and were fully aware of everything you were doing, warnings would be unnecessary. But brains fart regularly. And when they do, you might not even be aware of it were it not for those warnings ... and that puts the risks right off the scale.
      That applies to many warnings, yes... but not necessarily to those listed here. Personally, I can't easily recall warnings 'undef' ever having caught an actual problem in my code1, but it's constantly complaining about cases where nothing is wrong aside from my not having bothered to add an explicit default-to-zero or test-for-defined whose sole purpose is to shut warnings 'undef' up.

      1 Which is not to say that it hasn't ever caught an actual problem for me. I'm sure it has done so on at least several occasions. But they're so rare that I can't think of any offhand.

        It depends how you code. It is certainly easy to code in a way where 'undef' warnings are both common and uninteresting. And 'undef' warnings are easily the ones that are mostly likely to be annoyingly common and annoyingly uninteresting.

        But I usually code in a way where 'undef' warnings are much less common and much more likely to indicate a real mistake. I only rarely find myself disabling 'undef' warnings.

        My biggest disagreement with the original posting is that I've never seen "isn't numeric" be a warning that I would just ignore. That warning is almost always an indication of a serious problem when I run into it.

        I've only once been bitten by a bug caused by a reference being usable as a number without warning. But I agree that this could be extremely useful to be able to flag such things. I certainly want to be able to do $ref1 == $ref2. I very, very rarely even want to do things like pack "p", $ref. And 0+$ref, especially with a literal zero like that, should probably never cause a warning. But any other uses of the numeric value from a reference should generate a warning. Unfortunately, that looks rather difficult to implement in Perl, at least in some respects. Maybe not so bad if we just add a flag to scalars.

        Worse was when read-only access of undef as a reference could be fatal! But maybe all of those cases have now been fixed. I've always had a hard time remembering exactly how to reproduce this failure but gave up trying to reproduce it on a modern Perl today. I'm hopeful that this just isn't a problem in modern Perls.

        - tye        

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://1007936]
Approved by GrandFather
Front-paged by Old_Gray_Bear
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2017-04-30 15:19 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (541 votes). Check out past polls.