I\'ve seen obfuscated and golfed code that keeps is off to avoid declaring variables, and I can see skipping them on the command line with the -e switch to keep the one-liner sh
Doing use strict
and use warnings
helps someone understand exactly what Perl is doing.
Someone who understands exactly what Perl is doing and why, all of the time (i.e., pretty much nobody), would qualify for omitting them in order to save space and possibly execution time. Unfortunately, many of the people who want to save space and time are those who don't know exactly what Perl is doing and why, and their understanding of what Perl is doing is based on so many false assumptions learned from other languages, that they should absolutely never be allowed to omit them.
There are some other valid reasons as well:
use strict
or use warnings
, so "old" here means really, really old, like Perl version 4 or older)By the way, for programs accepting any input and performing actions on the basis of that input, it is also very important to use the -T
flag to help track the use of possibly tainted data obtained from user input.
Update: @mob makes a claim in a comment that bears some investigation, i.e., that not using strict and warnings is a micro-optimization below the point of even average insignificant microptimizations. In every case below, the real time for not using strict and warnings is 12 milliseconds, and in every case below, the real time for using them is 57 milliseconds or more.
So there is, just as I said originally, a possible benefit in execution time (that would only matter if you were doing something like embedding Perl scripts within templates and running 10 or 20 of them at a time every time a web page was loaded, for example), but it is still recommended that you use them unless you truly know exactly what Perl is doing and why, all of the time. My description of this category of "experts" is intended to be very close to the empty set. If you think you fall into this category, you automatically don't.
[j@5 ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.005s
sys 0m0.007s
[j@5 ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.010s
sys 0m0.005s
[j@5 ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.011s
sys 0m0.001s
[j@5 ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.004s
sys 0m0.007s
[j@5 ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.005s
sys 0m0.007s
[j@5 ~]$ time perl -e 'use strict; use warnings;'
real 0m0.058s
user 0m0.058s
sys 0m0.000s
[j@5 ~]$ time perl -e 'use strict; use warnings;'
real 0m0.057s
user 0m0.041s
sys 0m0.016s
[j@5 ~]$ time perl -e 'use strict; use warnings;'
real 0m0.057s
user 0m0.033s
sys 0m0.025s
[j@5 ~]$ time perl -e 'use strict; use warnings;'
real 0m0.057s
user 0m0.050s
sys 0m0.009s
The strict
pragma restricts you to a sane subset of Perl. Some old features make historic sense (or have benefits with one-liners), but have no place in a modern, readable code base.
The strict
pragma has three categories:
"vars"
Forces you to declare all your variables. This shields against typos, and makes sure you pick a scope (global/lexical). In a one-liner, this is not needed that much, as there are usually very few scopes, and very few variables. Some one-liner idioms wouldn't work with lexical variables only.
"refs"
disallows symrefs. They make no sense with lexical variables, and Perl5 has real references. So they are generally useless. However, symrefs remain valuable for metaprogramming:
# generate accessors
for my $field (qw/foo bar baz/) {
no strict 'refs';
*{ __PACKAGE__ . '::' . $field } = sub { shift()->{$field} };
}
"subs"
forces the interpretation of most barewords as subroutine calls. This resolves the ambiguity of foo . "bar"
to be foo() . "bar"
. If this category is not activated, and if no foo
sub is currently defined, then it would have parsed as "foo" . "bar"
. This makes sense to a shell programmer, where all barewords are strings. But in a Perl program, this drastically increases the cognitive load of the programmer, and is not worth it.
Summary: for simple scripts that don't optimize for readability, strict "vars"
isn't really neccessary. There are a few cases where no strict 'refs'
is desired.
The warnings
pragma allows fine grained control over warning messages. This is especially important for programmers new to Perl, who frequently write stuff like
my %hash = { foo => 1, bar => 2 };
and wonder where that HASH(0x1234567)
key came from. Even on a one-liner, warnings are desirable, except in cases where you use stringification of undef
etc.
In a professional codebase, there is no excuse for not using warnings
everywhere. If a script warns, it's very likely there is a bug, and no warnings
does not make this bug go away. Your knowledge of Perl is never as vast as that of the warnings
pragma. Even gurus make mistakes. use warnings
is a great debugging shortcut.
That said, it may be allright to comment the use warnings
when deploying the program. But never for development.
Depending on the consensus in the dev team, other pragmas should be used as well:
no indirect
disallows the loathed new Foo
method calls. I've seen bugs sneak in that could have been caught at compile time with this pragma.no autovivification
prevents references springing into existence on read-only operations like $hash{doesnt_exist}{foo}
.Sometimes strict
and warnings
prevent you from doing things you want to do, like doing certain manipulations on the symbol table that would violate strict 'refs'
, or redefining a subroutine where warnings 'redefine'
would be triggered. At other times it is more convenient to ignore certain warnings than to write defensive code against them, like a quick-and-dirty database dump for a table that might contain NULL/undef
values that would trigger warnings 'uninitialized'
.
use strict
and use warnings
, and their retardants no strict
and no warnings
can be locally scoped, so it is a best practice to disable strict
and warnings
in the smallest practical scope.
@data = get_some_data_from_database();
if (some_condition()) {
no warnings 'uninitialized';
logger->debug("database contains: @$_") for @data;
## otherwise, suppressing the warnings would take something
## less readable and more error-prone like:
# logger->debug("database contains: @{[map{defined?$_:''}@$_]}") for @data
# logger->debug("database contains: @{[map{$_//''}@$_]}") for @data
}
# end of scope, warnings `uninitialized' is enabled again