masks the following type of warning
when use warnings
is in effect:
Use of uninitialized value in range (or flip)
Here, we get the warning message, as desired:
$ perl -w -e 'my $x = 1..3'
Use of uninitialized value in range (or flip) at -e line 1.
Now, add diagnostics
so we can get a more verbose explanation
of the warning message:
$ perl -w -e 'my $x = 1..3' -Mdiagnostics
D'oh! Not only did diagnostics
not display additional information,
but it also made the warning message disappear. WTF?
Furthermore, if diagnostics is used in conjunction with
use warnings FATAL => 'all';
the script will not die because of the warning.
We can't use diagnostics
to get more information on this warning,
but we can still use splain
to do the job:
$ echo 'Use of uninitialized value in range (or flip)' | splain
Use of uninitialized value in range (or flip) (#1)
(W uninitialized) An undefined value was used as if it were alread
defined. It was interpreted as a "" or a 0, but maybe it was a mi
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl tells you what ope
you used the undefined value in. Note, however, that perl optimiz
program and the operation displayed in the warning may not necessa
appear literally in your program. For example, "that $foo" is
usually optimized into "that " . $foo, and the warning will refer
the concatenation (.) operator, even though there is no . in your
Well, this message is not all that helpful because it does not seem specific to this case. That's a separate
issue for perldiag
, which can be dealt with on another day.
Here is my hypothesis on why this happens.
A quote from Range Operator
If either operand of scalar ".." is a constant expression, that operand
is considered true if it is equal ("==") to the current input line
number (the $. variable).
By default, $.
$ perl -w -e 'print ">>>$.<<<\n"'
Use of uninitialized value in concatenation (.) or string at -e line 1
Unless you use diagnostics
$ perl -w -e 'print ">>>$.<<<\n"' -Mdiagnostics
So, it seems that diagnostics
has the side effect
of initializing the $.
variable. I see some calls
in the source code
is opening a file handle which
is giving the global $.
variable a value, thereby
suppressing the warning message.
If I modify diagnostics.pm
by adding the following line
, the problem is fixed:
This is a bug. Unless the monks can convince me otherwise,
I plan to submit this patch as a bug report via perlbug
--- diagnostics.pm 2009-06-15 04:21:42.000000000 -0400
+++ diagnostics.pm.fix 2009-12-05 10:29:53.096561000 -0500
@@ -222,6 +222,7 @@
local $| = 1;
my(%HTML_2_Troff, %HTML_2_Latin_1, %HTML_2_ASCII_7);
Until this gets fixed, make sure you use diagnostics
when you need it. Do not keep use diagnostics;
your code indefinitely. Unfortunately, I have done this in
many of my scripts, and I must now go back and comment them out.
This is similar to tye's advice in (tye)Re: use diagnostics eats memory?.
$ perl -v
This is perl, v5.10.0 built for x86_64-linux
The latest version I can find on CPAN is 1.18, and the issue
exists there too.
In trying to unravel a range operator mystery, a Super Search
led me to an observation by QM
. I could not see
the warning message because I had use diagnostics;
Update: Dec. 11, 2009: submitted bug report: http://rt.perl.org/rt3/Public/Bug/Display.html?id=71204
Update: Apr. 13, 2010: confirmed fix in perl version 5.12.0 ($VERSION of diagnostics.pm is 1.19)