Is there a difference between "use warnings;" and "use warnings 'all';"? - perl

I have the habit of starting each and every of my scripts with
use strict;
use warnings;
But some of the high-rep fellows here recommend
use warnings 'all';
If I understood them right, the latter is even better than the first. So I read through the docs and found
All warnings are enabled in a block by either of these:
use warnings;
use warnings 'all';
Even the Camel Book says nothing different:
use warnings; # same as importing "all"
So
is there a difference, or
is it just more future-proof (in case future versions of Perl issue warnings we aren't aware of right now and use warnings; won't catch), or
is it just another habit, like e.g. ps -ef vs. ps aux? Some people use this while others prefer the other.

Currently,
use warnings;
is equivalent to
use warnings 'all';
However, there has been talk on perl5porters of changing it to mean
use warnings 'default';
New "less-critical" warnings would be added to the "all" category but not shown by default. Since it seems this change is seriously being considered, it's safer to use warnings 'all'; explicitly.
Previous discussions on p5p:
RFC: Support for new warning categories outside of "all"
I've added support for new warning categories outside of "all" to blead

One is more explicit than the other, but as noted in the documentation, they have the same effect. It's probably better to use the 'all' import list to make it more clear that all warnings are in fact enabled. This is also helpful for those who may be new to Perl. When in doubt, explicit is usually better than implicit.

Related

Suppress uninitailized perl warning

Is there a way I can suppress uninitialized Perl variable warning for only few libraries out of all the libraries used in a Perl file?
I can't think of any reason this would be a good idea, surely use of an uninitialised variable is a bug which ever angle you look at it from?
However, you can turn the warnings off with:
no warnings 'uninitialized';
And on again with:
use warnings 'uninitialized';
You can disable the warnings for a single statement if you surround it with these two statements.
You probably used -w, which enables warnings throughout the interpreter (though it can be overridden using local $^W = 0; or no warnings;).
It's not a bad thing to use -w. All modules should tolerate this or defend against it (using no warnings;). But some aren't "warnings-safe".
It's more conventional to place use warnings; in each of your scripts and modules. This is method of enabling warnings is less intrusive since it won't affect other third-party modules used by your script and modules.
If you're able to modify the offending module(s), you can add no warnings 'uninitialized'; to the module itself, outside of any sub declarations, and it will disable that category of warnings for all code in the module, as demonstrated with these two bits of code:
In warntest:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use lib '.';
use UndefMod;
my $x;
say "Main before: $x";
UndefMod::test_mod;
say "Main after: $x";
In UndefMod.pm (in the same directory):
package UndefMod;
use strict;
use warnings;
use 5.010;
no warnings 'uninitialized';
sub test_mod {
my $x;
say "Module: $x";
}
1;
When run, this produces "Use of uninitialized value" warnings for both says in warntest, but no warning for the say in UndefMod, thus showing that either file's warnings setting has no effect on the other.
Of course, you may not be able to modify the module source, in which case you may be out of luck. Perl's scoping rules don't generally allow you to modify the warnings/no warnings state of a scope from outside that scope. (I say "may" and "generally" because there may be some black magic to hack around that, probably at least related to the magic behind PadWalker, but such things are beyond my ken.)

MOJO perl Deprecated warnings

I am learning Mojo, this is my first script and it works fine - that is it does what i want it to do.
use Mojo::UserAgent;
use Mojo::DOM;
use Mojo::Collection;
use strict;
use warnings;
my $ua = Mojo::UserAgent ->new;
my $dom = Mojo::DOM ->new;
$dom = $ua->get('http://lalalala....')->res->dom;
open (my $file_zlec, "> zlc2012.csv") or die "couldn't open file!";
binmode $file_zlec, ":utf8";
for my $zlec($dom->find('table.tbl_zlc')->each){
print "$i \n"; $i++;
wypisz($zlec, 'td.tbl_zlc_d1',1);
print $file_zlec"\n";
}
sub wypisz{
my $ch= $_[0]-> find($_[1])->children;
if ($_[2]==1){
my $tekst = $ch->text;
print $file_zlec "$tekst;";
}
my $href= $ch->map(attr => 'href');
if (not $href=~/lalala\.pl/g) {$href="www.lalala.pl".$href};
print $file_zlec "$href;";
}
However, a get a lot of warnings regarding "children", "text" and "attr":
'Mojo::Collection::AOUTOLOAD (..) is DEPRECATED in favor of MOJO::Collection::map at (..)'
'Stringifacation support in Mojo::Collection::AOUTOLOAD (...) is DEPRECATED in favor of Mojo::Collection::join at (..)
I thought i was doing smth wrong, but I followed the example at http://mojocasts.com/e5 EXCACTLY and got the same warnings
use Mojo::UserAgent;
my $ua = Mojo::UserAgent ->new;
print $ua->get('http://mojolicio.us')->res->dom->html->head->title;
My questions are:
1. should i worry? like i said, scripts works fine
2. if ans(1) is no, is there a way to turn this off? i can't see anything in a command line..
Okay it looks like these deprecations have been added recently. For example the AUTOLOAD deprecation was introduced at the end of October this year, and my version of Mojolicious preceded that so I wasn't seeing the messages you were getting. I've now upgraded my installation and understand the problem.
Unfortunately, the Mojolicious DEPRECATED messages are generated by the Carp module and they don't respond to the no warnings pragma. The only way I know to disable then is to set the warning handler to a null subroutine, like this
$SIG{__WARN__} == sub { };
but that is very heavy-handed as it silences all warnings instead of just the nuisance ones you are seeing.
Since the facility you are using is deprecated, it is likely to be removed from the Mojolicious suite in the near future, so it is best anyway if you learn to adopt the new standard from the outset.
The message says
Mojo::DOM::AUTOLOAD (html) is DEPRECATED in favor of Mojo::DOM::children
which means that they would prefer that you used $dom->children('html') instead of just $dom->html. But children returns a Mojo::Collection object, which is a set of nodes, so you need to select the first item of that collection. That turns
$dom->html->head->title
into the cumbersome
$dom->children('html')->first->children('head')->first->children('title')->first
so it is far better to use the at method which takes a CSS3 expression, and you can write
$dom->at('html > head > title')
which is fine, and generates no warnings. Note that it isn't an exact replacement for the children/first chain, as the entire document is being searched for a title node that is a child of a head node that is a child of an html node. But since the only place that this can occur is at the root of the document, the result is identical. Even this can be fixed by using the CSS3 item :root in place of html.
The complete program would look like this
use strict;
use warnings;
use Mojolicious;
my $ua = Mojo::UserAgent->new;
my $dom = $ua->get('http://mojolicio.us')->res->dom;
print $dom->at('html > head > title')->text;
output
Mojolicious - Perl real-time web framework
"should i worry"
You should aim to remove all warning messages that a program generates. You first need to understand exactly why you are getting them, and then you can make the choice to write your code differently or to temporarily disable the warnings once you are certain that the problem is benign.
As a guide, I disable warnings in much less than one percent of my programs. They are almost always an indication of a coding problem that can and should be resolved.

'use warnings' vs. '#!/usr/bin/perl -w' Is there a difference?

I read that it is better to use warnings; instead of placing a -w at the end of the shebang.
What is the difference between the two?
The warnings pragma is a replacement for the command line flag -w, but the pragma is limited to the enclosing block, while the flag is global. See perllexwarn for more information and the list of built-in warning categories.
– warnings documentation
The advantage of use warnings is that it can be switched off, and only affects the immediate scope.
Consider for example a module that uses operations that would emit warnings:
package Idiotic;
sub stuff {
1 + undef;
}
Then we get a warning if we do
#!perl -w
use Idiotic; # oops, -w is global
Idiotic::stuff();
but don't get any warning with
#!perl
use warnings; # pragmas are scoped, yay!
use Idiotic;
Idiotic::stuff();
Yes, there is a difference, from warnings:
The warnings pragma is a replacement for the command line flag -w ,
but the pragma is limited to the enclosing block, while the flag is
global.
-w will enable warnings in included code (via use, etc.), and that may not be desirable.

Why are use warnings; use strict; not default in Perl?

I'm wondering why
use warnings;
use strict;
are not default in Perl. They're needed for every script. If someone (for good reason) needs to disable them, they should use no strict and/or should use some command line argument (for one-liners).
Are there too many badly-written CPAN modules (using "badly" to mean without use strict)? Or is it because this can break a lot of code already in production? I'm sure there is a reason and I would like to know it.
In 5.14 IO::File is loaded automagically on demand, wouldn't it be possible to do something like that with these basic pragmas?
It's for backwards compatibility. Perl 4 didn't have strict at all, and there are most likely still scripts out there originally written for Perl 4 that still work fine with Perl 5. Making strict automatic would break those scripts. The situation is even worse for one-liners, many of which don't bother to declare variables. Making one-liners strict by default would break probably millions of shell scripts and Makefiles out there.
It can't be loaded automagically, because it adds restrictions, not features. It's one thing to load IO::File when a method is called on a filehandle. But activating strict unless the code did something prohibited by strict is meaningless.
If a script specifies a minimum version of 5.11.0 or higher (e.g. use 5.012), then strict is turned on automatically. This doesn't enable warnings, but perhaps that will be added in a future version. Also, if you do OO programming in Perl, you should know that using Moose automatically turns on both strict and warnings in that class.
If you are on a modern Perl, say so, you just have to enable it. 5.12 applies strict except for one-liners. It can't be default because of backward compatibility.
$ cat strict-safe?.pl
use 5.012;
$foo
$ perl strict-safe\?.pl
Global symbol "$foo" requires explicit package name at strict-safe?.pl line 2.
Execution of strict-safe?.pl aborted due to compilation errors.
Well, use strict is default now, sort of.
Since Perl 5.12.0 if you require a version of Perl >= 5.12.0, then your script will have all the backwards incompatible features turned on, including strict by default.
use 5.12.0;
use warnings;
Is the same as:
use strict;
use warnings;
use feature ':5.12';
It hasn't been turned on more broadly because doing so would break a lot scripts that people depend on to "just work".
Moose also automatically turns on strict and warnings when you use it. So if you do any Moose based Perl OOP, then you get a free pass here, too.
It's a philosophical question, not a "it won't work" question.
First, perl has always been under the "you can do it incorrectly if you want" type of paradigm. Which is why there are a lot of perl haters out there. Many would prefer that the language always force you to write good code, but many quick-script-hackers don't want to. Consider:
perl -e '#a = split(/[,:]/, $_); print $a[1],"\n";'
Now, it would be easy to add a 'my' in front of the #a, but for a one line, one-time script people don't want to do that.
Second, yes, I think most of CPAN would indeed need to be rewritten.
There isn't a good answer you'll like, I'm afraid.
Both warnings and strict will finally be default (along with some Perl 5 features that were not defaults) with Perl 7. It is expected to be released in the first half of 2021 (with a release candidate maybe around the end of 2020). Maybe it will be out around May 18th to mark the 10 year anniversary of this question? Better late than never!
You can use the common::sense module, if you need:
use utf8;
use strict qw(vars subs);
use feature qw(say state switch);
no warnings;
use warnings qw(FATAL closed threads internal debugging pack
portable prototype inplace io pipe unpack malloc
deprecated glob digit printf layer
reserved taint closure semicolon);
no warnings qw(exec newline unopened);
It reduces the memory usage.

warnings::warn and FATAL categories in Perl

I must be understanding the warnings documentation wrong. The way I read it, this code:
use warnings;
use warnings FATAL => 'all';
warnings::warn('numeric', 'blarg');
print "finished\n";
Should print the 'blarg' warning and die since I've asked for all warnings to be fatal. However, when I run the code I get:
$> /opt/local/bin/perl x.pl
blarg at x.pl line 3
finished
Can somone help me understand why I can't get warn to die?
Okay. This is ugly. I had a post half-prepared explaining this as a bug in warnings, and then I realized it's not, it's just a really evil subtlety in the way warnings works.
Warnings starts looking for a relevant stack frame to get the warning bits from in warnings::warn's caller's caller. The idea is that you're writing some module and you use warnings::warn or warnings::warnif in your functions, and whether or not the warning is printed (or fatal) depends on the use warnings setting in scope in the code that uses your module. There's no option provided to have it start at caller(1) instead of caller(2), so the effect you want isn't possible.
An example of code that does work (and demonstrates how this interface was expected to be used by whoever wrote it):
package Foo;
require warnings;
sub bail {
warnings::warnif('numeric', "You fool! You divided by zero!");
}
package main;
use warnings FATAL => all;
Foo::bail();
print "Will never be reached\n";
And you can't defeat the way it works by just adding another level of subroutines, because it takes the flags from the first caller that's in a different package from the caller of warn/warnif/enable/etc.