When I try this code:
use strict;
use warnings;
print (44+66)/2;
It gave me:
Useless use of division (/) in void context at p.pl line 3.
But, after some tries, it worked by adding extra outer parentheses around the expression like:
use strict;
use warnings;
print ((44+66)/2);
And it did work!
Can anybody explain why?
Using Deparse will give you more information about how perl is parsing your code:
perl -MO=Deparse p.pl
Useless use of division (/) in void context at p.pl line 3.
use warnings;
use strict;
print(110) / 2;
p.pl syntax OK
Here you can see that the expression in the parens was evaluated as expected (66+44 = 110). But, then perl passes 110 as input to print, then tries to divide the output of print by 2.
Another helpful tool is diagnostics:
perl -Mdiagnostics p.pl
Useless use of division (/) in void context at p.pl line 3 (#1)
(W void) You did something without a side effect in a context that does
nothing with the return value, such as a statement that doesn't return a
value from a block, or the left side of a scalar comma operator. Very
often this points not to stupidity on your part, but a failure of Perl
to parse your program the way you thought it would.
It's great that you enabled warnings because it alerted you that there could be a problem with your code. When we run the code, we get 110 as output, whereas you expected 55.
The space between a function name and the opening parenthesis for the function call is optional. So when you write:
print (44+66)/2;
# ^ optional space!
Perl is assuming that you want to divide print(44+66) by 2 and then ignore the answer. So Perl warns you about performing an unnecessary division operation.
# workaround
print( (44+66)/2 );
# other workaround
print +(44+66)/2;
Related
I've got some legacy code that I'm dealing with. It's too much to clean up in one shot. It's using \1 inside of the s operator. I looked into perllexwarn and found I can shut it off with 'no warnings qw(syntax)', but I did this with trial and error. Is there an easier way to get right from the warning to the way to shut it off?
It's doing stuff like this:
use strict;
$_ = "abc";
s/abc/\1/;
no warnings qw(syntax);
s/abc/\1/;
the message it generates is :
\1 better written as $1
Execute your script as
perl -Mdiagnostics ./a.pl
or temporarily add use diagnostics; to your script. This will produce something like
\1 better written as $1 at ./a.pl line 4 (#1)
(W syntax) Outside of patterns, backreferences live on as variables.
The use of backslashes is grandfathered on the right-hand side of a
substitution, but stylistically it's better to use the variable form
because other Perl programmers will expect it, and it works better if
there are more than 9 backreferences.
Notice the (W syntax)? The letter is one of the following, and the word is the warning class for which you are looking.
(W) A warning (optional).
(D) A deprecation (enabled by default).
(S) A severe warning (enabled by default).
(F) A fatal error (trappable).
(P) An internal error you should never see (trappable).
(X) A very fatal error (nontrappable).
(A) An alien error message (not generated by Perl).
diagnostics gets its information from perldiag, which you could search manually instead of using use diagnostics;.
Other examples:
$ perl -Mdiagnostics -we'print undef'
Use of uninitialized value in print at -e line 1 (#1)
(W uninitialized) An undefined value was used as if it were already
[...]
$ perl -Mdiagnostics -we'no warnings qw( uninitialized ); print undef'
$ perl -Mdiagnostics -we'sub foo { } sub foo { }'
Subroutine foo redefined at -e line 1 (#1)
(W redefine) You redefined a subroutine. To suppress this warning, say
[...]
$ perl -Mdiagnostics -we'no warnings qw( redefine ); sub foo { } sub foo { }'
$
I'd make a global signal handler, set it in a BEGIN block so it's compiled in early, and skip only the warning you don't want, so you still get any potential unexpected and unrelated warnings (even within the same category, due to not having to disable the whole thing):
use warnings;
use strict;
BEGIN {
$SIG{__WARN__} = sub {
my $warn = shift;
return if $warn =~ /\\\d better written as/;
warn $warn;
};
}
my $x = 'abc';
$x =~ s/(abc)/\1/;
warn "a different warning\n";
Output:
a different warning
You can look the message up in perldoc perldiag. This will tell you the warning category it's in.
I was writing a module as part of my application when I noticed syntax check results in warning about useless use of a constant (1). Why is that?
The constant is the obligatory 1 at the end of the module which is normally ignored by warnings as perldoc perldiag says:
This warning will not be issued for numerical constants equal to 0 or 1 since they are often used in statements like
1 while sub_with_side_effects();
(There's probably an even better source for that. After all 1 at the end of files is totally desired and not to be warned about.)
But the warning is generated even for nearly empty modules if they use bigint.
package Foo;
use bigint;
1;
For this simple file syntax check produces the following warning:
$> perl -Wc Foo.pm
Useless use of a constant (1) in void context at Foo.pm line 5.
Foo.pm syntax OK
I could not find any reference to bigint and the warning message except Put long hex numbers in sqlite but this doesn't really address my issue, I think.
My Perl is v5.14.4 on Cygwin with bigint 0.36.
There are two issues at hand here.
Why does use bigint; 1; warn in void context?
Why is the constant being executed in void context in the first place?
$ perl -c -we'1 while sub_with_side_effects();'
-e syntax OK
$ perl -c -we'use bigint; 1 while sub_with_side_effects();'
Useless use of a constant (1) in void context at -e line 1.
-e syntax OK
Why does use bigint; 1; warn in void context?
use bigint; installs a callback that's called when a constant literal is encountered by the parser, and the value returned by the callback is used as the constant instead. As such, under use bigint;, 1 is no longer truly just a simple 0 or 1.
But you're not doing anything wrong, so this warning is spurious. You can work around it by using () or undef instead of 1.
undef while sub_with_side_effects();
Unless I needed to use it throughout my code base, I would favour the following:
while ( sub_with_side_effects() ) { }
$ cat Module.pm
package Module;
use bigint;
1;
$ perl -c -w Module.pm
Useless use of a constant (1) in void context at Module.pm line 3.
Module.pm syntax OK
Why is the constant being executed in void context?
When Perl executes a module, Perl expects the module to return a scalar value, so Perl should be executing the module in scalar context.
However, you told Perl to compile the script Module.pm. When Perl executes a script, Perl doesn't require any values to be returned, so Perl executes the script in void context.
Using a module as a script can cause spurious warnings and errors, and so can passing -W. Test a module using as follows:
perl -we'use Module'
Actually, you shouldn't even need -w since you should already have use warnings; in the module. All you really need is
perl -e'use Module'
-W instead of use warnings; in your module or checking modules with -c instead of perl -MFoo -e0 can show spurious errors. This is an example of the latter.
When you load a module normally, it isn't in void context, because it is checking that the result is true.
(Note that when I try it using 5.20.1, the -W also results in a spurious overload arg '..' is invalid at /usr/share/perl/5.20/Math/BigInt.pm line 155.)
Just leaving here a workaround to avoid the warning: Defining a constant with value 1 before using bigint:
package Foo;
use strict;
use warnings;
use constant PACKAGE_END => 1;
use bigint;
PACKAGE_END;
I get the following warning:
"Use of uninitialized value in concatenation (.) or string at C:\tools\test.pl line 17, DATA line 1."
But the next line of __DATA__ will be processed without any warning and get these:
test1b.txt:test test1c.txt:test :test
More strange thing is that when I add a line: print "$line:".$'."\n"; The warning disappeared.
Anybody have some clues?
#!/usr/bin/perl -w
use strict;
my $pattern='test';
my $output='$&';
while(<DATA>)
{
chomp;
my $line=$_;
chomp($line);
$line=~/$pattern/;
#print "$line:".$&."\n"; #why uncommenting this line make the following line pass without no warning.
my $result="$line:".eval($output)."\n";
print $result;
}
__DATA__
test1a.txt
test1b.txt
test1c.txt
Perl considers $&, $', and $` to be expensive, so it won't actually populate them in a program that doesn't use them. From the perlvar manpage:
The use of this variable [$&] anywhere in a program imposes a considerable
performance penalty on all regular expression matches. To avoid this
penalty, you can extract the same substring by using #-. Starting
with Perl 5.10, you can use the /p match flag and the ${^MATCH}
variable to do the same thing for particular match operations.
However, when you only use them inside a string that you pass to eval, Perl can't tell that you're using them, so it won't populate them, so they'll be undefined.
I have written some code, and I am not sure what the error is. I am getting the error:
Use of uninitialized value in concatenation (.) or string at mksmksmks.pl line 63
My code is as follows:
for(my $j = 0; $j < $num2; $j++) {
print {$out} "$destination[$j]|$IP_one_1[$j]|$IP_one_2[$j]|$reached[$j]|$IP_two_1[$j]|$IP_two_2[$j]\n";`
}
What it means is that one of the elements of either #destination, #IP_one_1, #IP_one_2, or #reached has not been defined (has not been assigned a value), or has been assigned a value of undef. You either need to detect (and prevent) undefined values at the source, or expect and deal with them later on. Since you have warnings enabled (which is a good thing), Perl is reminding you that your code is trying to concatenate a string where one of the values being concatenated is undefined.
Consider the following example:
perl -wE 'my #x = (); $x[0] = "Hello "; $x[2] = "world!"; say "#x"'
In this example, $x[0] has a value, and $x[2] has a value, but $x[1] does not. When we interpolate #x into a double-quoted construct, it is expanded as [element 0 (Hello )]<space>[element 1 (undef)]<space>[element 2 (world!)]. The undef elements interpolates as an empty string, and spews a warning. And of course by default array interpolation injects a space character between each element. So in the above example we see Hello <interpolation-space>(undef upgrades to empty string here)<interpolation-space>world!
An example of where you might investigate is one or more of the arrays is of a different total size than the others. For example, if #IP_one_2 has fewer elements than the others, or if $num2 is a value greater than the number of elements in any of the arrays.
Place the following near the top of your script and run it again:
use diagnostics;
When I run the following one-liner under warnings and diagnostics:
$ perl -wMdiagnostics -e '$a=$a; print "$a\n"'
I get the following output, and you will get something similar if you add use diagnostics;... a very helpful tool when you're first learning Perl's warnings.
Use of uninitialized value $a in concatenation (.) or string at -e
line 1 (#1)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl will try to tell you
the name of the variable (if any) that was undefined. In some cases
it cannot do this, so it also tells you what operation you used the
undefined value in. Note, however, that perl optimizes your program
anid the operation displayed in the warning may not necessarily appear
literally in your program. For example, "that $foo" is usually
optimized into "that " . $foo, and the warning will refer to the
concatenation (.) operator, even though there is no . in
your program.
Maybe my example will be useful to someone. Suppose variable $x is initialized from a database. It may contain an undefined value, and this is normal. We need to display its value on the console. As responsible programmers, we decided to use "use warnings FATAL => "all";". In this case, the script will fail.
perl -e 'use strict; use warnings FATAL => "all"; my $x; print("x=$x\n"); print("DONE\n");'
Returns:
Use of uninitialized value $x in concatenation (.) or string at -e line 1.
In this case, you can use
if(defined($x)){...}else{...}
But this is not pretty if just want to print a value.
perl -e 'use strict; use warnings FATAL => "all"; my $x; print("x=".($x//"null")."\n"); print("DONE\n");'
Prints:
x=null
DONE
Because the expression $x//"null" checks whether what comes before // is defined and if it is not defined returns what comes after //.
If you use eq "" it won't give any warning message.
But if you use eq " " (here you can see a space), then it will give this warning message:
Use of uninitialized value in concatenation (.) or string ....
Given a method that may fail with warnings and/or errors, I want the error method to show up at the caller. Fir instance this script:
foo(0); # line 1
sub foo {
1 / shift; # line 4
}
Produces the error Illegal division by zero at foo.pl line 4, but I want Illegal division by zero at foo.pl line 1. There should be several ways if I put the method in a module or if I wrap the method body in eval, but I have not found an easy way like this:
sub foo {
attributeErrorsToCaller; # do some magic
1 / shift;
}
Is there such a way?
EDIT: mirod's answer comes close not what I was looking for:
Foo::foo(0); # line 1
package Foo;
use diagnostics -traceonly;
BEGIN { disable diagnostics; }
sub foo {
enable diagnostics;
1 / shift; # line 9
}
Without enable diagnostics the error message is Illegal division by zero at foo.pl line 9.. With enable diagnostics it is still too verbose, but this may also be useful:
Uncaught exception from user code:
Illegal division by zero at foo.pl line 10.
at foo.pl line 10
Foo::foo(0) called at foo.pl line 2
I bet I could hack diagnostics to get exactely the feature I want, but using diagnostics as raw module is probably more recommended.
Carp is very, very close to "do_some_magic" you are asking for. For instance:
#!/usr/bin/perl -w
use strict;
# I fork to be as close to natural die() as possible.
fork() or Foo::foo();
fork() or Foo::bar();
fork() or Foo::baz();
sleep 1;
package Foo;
use Carp;
sub foo { die "Some error (foo)"; };
sub bar { croak "Some error (bar)"; };
sub baz { bar(); };
As you can see, croak() acts almost like die(), but reports error to the caller (even indirectly -- see baz).
However, it won't handle 1/0 for you -- either use eval (or even Try::Tiny), or check input values* and say "division by zero" yourself.
Carp is standard, which means understandable by further maintainers of your code, and also can print neat stack traces via confess or cluck or even print Carp::longmess (see the doc).
*which is good anyway
Would use diagnostics; be enough for you? It will dump the call stack, so the caller is quite easy to find out.
For example in you example:
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
foo(0);
sub foo
{
return 1/$_[0];
}
gives this:
`Illegal division by zero at test_die line 12 (#1)
(F) You tried to divide a number by 0. Either something was wrong in
your logic, or you need to put a conditional in to guard against
meaningless input.
Uncaught exception from user code:
Illegal division by zero at test_die line 12.
at test_die line 12
main::foo(0) called at test_die line 8
Not like you describe. You can implement Debug::Trace to pull off a full back trace.
You may also find the perl caller which is quite useful for this type of debugging. But for a live application you will likely need to do more detailed tracing.
http://perldoc.perl.org/functions/caller.html