Why are use warnings; use strict; not default in Perl? - 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.

Related

Can I `use strict` to observe runtime error? [duplicate]

When using use strict perl will generate a runtime error on unsafe constructs. Now I am wondering if it is possible to have it only print a warning instead of causing a runtime error ? Or is use warnings (or -w) warning about the same issues ?
No, use strict can't be made to issue warnings rather than die. All it does is set a few bits in the magic $^H variable, which triggers various things in the guts of the Perl interpreter.
No, use warnings isn't warning about the same things as use strict kills you for. For instance, use warnings will warn you about variables used only once (which might be the result of typos).
I'm gonna take a stab at guessing the real motivation here. Feel free to tell me if I guessed wrong.
I suspect your trying to tackle a large, older code base and would like to enable strictures but you were hoping first to get a sense of where the errors will be (and how many there are) without breaking functionality. Unfortunately, since use strict functions by modifying the internal behavior of the perl parser and interpreter, there isn't a 'loose strict' or, by analogy to html, any kind of 'transitional' mode.
However, you can tease apart the functionality of use strict to start moving in the right direction. First, note that there are actually three separate parts:
use strict 'refs'; # no symbolic references
use strict 'vars'; # must declare variables
use strict 'subs'; # no barewords
and of those only 'refs' generates runtime errors. So you could easily add use strict qw(vars subs) to each of your files (scripts and modules) and test them with perl -c. If you encounter any error messages, then comment out the use strict, or at least whichever of the two checks failed, and add a comment as to the nature of the failure and move on. This way you can quickly (depending on the number of files) determine which files have compile-time errors and come back to address them later. (If you were more motivated than me at the moment, you could even automate this process). Unless you have code that does scary things inside of BEGIN blocks, this should be pretty safe to do.
The trickier part is checking for the runtime errors generated by use strict 'refs' and unfortunately, there really isn't an easy way to do this because the errors are triggered by symbolic references which can't be determined by any kind of static analysis so -c and/or Perl::Critic are both useless.
Hopefully that gets closer to addressing your real problem.
The warnings and strict pragmas are complementary, not overlapping. The strict pragma has both compile-time and run-time effects. You can't reduce the severity of strictures from errors to warnings, but you can disable them entirely. For example, if you're writing your own export routine you'll need to enable symbolic references in order to manipulate the symbol table.
{
no strict 'refs';
# symrefs okay within this block
}
Warnings can also be disabled lexically (assuming you did use warnings instead of the largely obsolete -w flag).
Strictures and warnings provide a safety net. That's why they're recommended to be used by default. If you disable them you should disable only what's necessary and limit the change to the smallest possible scope.
The preferred method:
use Carp;
sub foo {
croak "no args" unless #_;
}
eval foo();
if( $# ){
print "caught die: $#";
}
If you can't change your die's to croak's:
sub foo {
die "no args" unless #_;
}
{
my $prev_die = $SIG{__DIE__};
$SIG{__DIE__} = sub { print "caught die: $_[0]"; };
eval foo();
$SIG{__DIE__} = $prev_die;
}
The second method will print out the errors on STDERR.
See:
perldoc -f eval
perldoc perlvar and search for /\$\#/ and /__DIE__/
perldoc Carp
Warnings can be made fatal — see perllexwarn — but strict errors can't be made non-fatal.
Why do you want to do that? I suspect an XY problem.

why do i have to specify "use feature :5.1x" even when my installed perl is 5.14?

I have 5.14.2 installed in my machine but when i try to execute a print statement with say keyword it gives me error.
I have go with the use keyword to make the program run without error.
#!/usr/bin/perl
use feature ':5.10';
say "hello";
5.14.2 is latest when compared to 5.010 so it should have all those features enabled by default right ? then what is the point in specifying the version using use keyword ?
Perl attempts to maintain backward compatibility. It's quite possible that existing scripts might have subroutines named say. There is considerable on-going discussion of whether or not some future version of Perl should stop these efforts and streamline its internals. See, for instance, naming and numbering perl .
It prevents conflicts with existing programs written in Perl.
For example, say I wrote a program for Perl 5.6 which defined a subroutine called say.
use strict;
use warnings;
sub say { print 1; }
say();
That works fine (outputting 1), and it still works in perls that include the say feature.
Now let's enable the native say and see what happens:
use v5.14;
use strict;
use warnings;
sub say { print 1; }
say();
Now it falls over with *Use of uninitialized value $_ in say at - line 5.*
You need to use feature or use v5.xx so that the new features can be loaded safely, i.e. when the author knows he wants to use them.

Having a perl script make use of one among several secondary scripts

I have a main program mytool.pl to be run from the command line. There are several auxillary scripts special1.pl, special2.pl, etc. which each contain a couple subroutines and a hash, all identically named across scripts. Let's suppose these are named MySpecialFunction(), AnotherSpecialFunction() and %SpecialData.
I'd like for mytool to include/use/import the contents of one of the special*.pl files, only one, according to a command line option. For example, the user will do:
bash> perl mytool.pl --specialcase=5
and mytools will use MySpecialFunction() from special5.pl, and ignore all other special*.pl files.
Is this possible and how to do it?
It's important to note that the selection of which special file to use is made at runtime, so adding a "use" at the top of mytool.pl probably isn't the right thing to do.
Note I am a long-time C programmer, not a perl expert; I may be asking something obvious.
This is for a one-off project that will turn to dust in only a month. Neither mytool.pl nor special?.pl (nor perl itself) will be of interest beyond the end of this short project. Therefore, we don't care for solutions that are elaborate or require learning some deep magic. Quick and dirty preferred. I'm guessing that Perl's module mechanism is overkill for this, but have no idea what the alternatives are.
You can use a hash or array to map values of specialcase to .pl files and require or do them as needed.
#!/usr/bin/env perl
use strict; use warnings;
my #handlers = qw(one.pl two.pl);
my ($case) = #ARGV;
$case = 0 unless defined $case;
# check that $case is within range
do $handlers[$case];
print special_function(), "\n";
When you use a module, Perl just require's the module in a BEGIN block (and imports the modules exported items). Since you want to change what script you load at runtime, call require yourself.
if ($special_case_1) {
require 'special1.pl';
# and go about your business
}
Here's a good reference on when to use use vs. require.

Why use strict and warnings?

It seems to me that many of the questions in the Perl tag could be solved if people would use:
use strict;
use warnings;
I think some people consider these to be akin to training wheels, or unnecessary complications, which is clearly not true, since even very skilled Perl programmers use them.
It seems as though most people who are proficient in Perl always use these two pragmas, whereas those who would benefit most from using them seldom do. So, I thought it would be a good idea to have a question to link to when encouraging people to use strict and warnings.
So, why should a Perl developer use strict and warnings?
For starters, use strict; (and to a lesser extent, use warnings;) helps find typos in variable names. Even experienced programmers make such errors. A common case is forgetting to rename an instance of a variable when cleaning up or refactoring code.
Using use strict; use warnings; catches many errors sooner than they would be caught otherwise, which makes it easier to find the root causes of the errors. The root cause might be the need for an error or validation check, and that can happen regardless or programmer skill.
What's good about Perl warnings is that they are rarely spurious, so there's next to no cost to using them.
Related reading: Why use my?
Apparently use strict should (must) be used when you want to force Perl to code properly which could be forcing declarations, being explicit on strings and subs, i.e., barewords or using refs with caution. Note: if there are errors, use strict will abort the execution if used.
While use warnings; will help you find typing mistakes in program like you missed a semicolon, you used 'elseif' and not 'elsif', you are using deprecated syntax or function, whatever like that. Note: use warnings will only provide warnings and continue execution, i.e., it won't abort the execution...
Anyway, it would be better if we go into details, which I am specifying below
From perl.com (my favourite):
use strict 'vars';
which means that you must always declare variables before you use them.
If you don't declare you will probably get an error message for the undeclared variable:
Global symbol "$variablename" requires explicit package name at scriptname.pl line 3
This warning means Perl is not exactly clear about what the scope of the variable is. So you need to be explicit about your variables, which means either declaring them with my, so they are restricted to the current block, or referring to them with their fully qualified name (for ex: $MAIN::variablename).
So, a compile-time error is triggered if you attempt to access a variable that hasn't met at least one of the following criteria:
Predefined by Perl itself, such as #ARGV, %ENV, and all the global punctuation variables such as $. Or $_.
Declared with our (for a global) or my (for a lexical).
Imported from another package. (The use vars pragma fakes up an import, but use our instead.)
Fully qualified using its package name and the double-colon package separator.
use strict 'subs';
Consider two programs
# prog 1
$a = test_value;
print "First program: ", $a, "\n";
sub test_value { return "test passed"; }
Output: First program's result: test_value
# prog 2
sub test_value { return "test passed"; }
$a = test_value;
print "Second program: ", $a, "\n";
Output: Second program's result: test passed
In both cases we have a test_value() sub and we want to put its result into $a. And yet, when we run the two programs, we get two different results:
In the first program, at the point we get to $a = test_value;, Perl doesn't know of any test_value() sub, and test_value is interpreted as string 'test_value'. In the second program, the definition of test_value() comes before the $a = test_value; line. Perl thinks test_value as sub call.
The technical term for isolated words like test_value that might be subs and might be strings depending on context, by the way, is bareword. Perl's handling of barewords can be confusing, and it can cause bug in program.
The bug is what we encountered in our first program, Remember that Perl won't look forward to find test_value(), so since it hasn't already seen test_value(), it assumes that you want a string. So if you use strict subs;, it will cause this program to die with an error:
Bareword "test_value" not allowed while "strict subs" in use at
./a6-strictsubs.pl line 3.
Solution to this error would be
Use parentheses to make it clear you're calling a sub. If Perl sees $a = test_value();,
Declare your sub before you first use it
use strict;
sub test_value; # Declares that there's a test_value() coming later ...
my $a = test_value; # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }
And If you mean to use it as a string, quote it.
So, This stricture makes Perl treat all barewords as syntax errors. A bareword is any bare name or identifier that has no other interpretation forced by context. (Context is often forced by a nearby keyword or token, or by predeclaration of the word in question.) So If you mean to use it as a string, quote it and If you mean to use it as a function call, predeclare it or use parentheses.
Barewords are dangerous because of this unpredictable behavior. use strict; (or use strict 'subs';) makes them predictable, because barewords that might cause strange behavior in the future will make your program die before they can wreak havoc
There's one place where it's OK to use barewords even when you've turned on strict subs: when you are assigning hash keys.
$hash{sample} = 6; # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );
Barewords in hash keys are always interpreted as strings, so there is no ambiguity.
use strict 'refs';
This generates a run-time error if you use symbolic references, intentionally or otherwise.
A value that is not a hard reference is then treated as a symbolic reference. That is, the reference is interpreted as a string representing the name of a global variable.
use strict 'refs';
$ref = \$foo; # Store "real" (hard) reference.
print $$ref; # Dereferencing is ok.
$ref = "foo"; # Store name of global (package) variable.
print $$ref; # WRONG, run-time error under strict refs.
use warnings;
This lexically scoped pragma permits flexible control over Perl's built-in warnings, both those emitted by the compiler as well as those from the run-time system.
From perldiag:
So the majority of warning messages from the classifications below, i.e., W, D, and S can be controlled using the warnings pragma.
(W) A warning (optional)
(D) A deprecation (enabled by default)
(S) A severe warning (enabled by default)
I have listed some of warnings messages those occurs often below by classifications. For detailed info on them and others messages, refer to perldiag.
(W) A warning (optional):
Missing argument in %s
Missing argument to -%c
(Did you mean &%s instead?)
(Did you mean "local" instead of "our"?)
(Did you mean $ or # instead of %?)
'%s' is not a code reference
length() used on %s
Misplaced _ in number
(D) A deprecation (enabled by default):
defined(#array) is deprecated
defined(%hash) is deprecated
Deprecated use of my() in false conditional
$# is no longer supported
(S) A severe warning (enabled by default)
elseif should be elsif
%s found where operator expected
(Missing operator before %s?)
(Missing semicolon on previous line?)
%s never introduced
Operator or semicolon missing before %s
Precedence problem: open %s should be open(%s)
Prototype mismatch: %s vs %s
Warning: Use of "%s" without parentheses is ambiguous
Can't open %s: %s
These two pragmas can automatically identify bugs in your code.
I always use this in my code:
use strict;
use warnings FATAL => 'all';
FATAL makes the code die on warnings, just like strict does.
For additional information, see: Get stricter with use warnings FATAL => 'all';
Also... The strictures, according to Seuss
There's a good thread on perlmonks about this question.
The basic reason obviously is that strict and warnings massively help you catch mistakes and aid debugging.
Source: Different blogs
Use will export functions and variable names to the main namespace by
calling modules import() function.
A pragma is a module which influences some aspect of the compile time
or run time behavior of Perl. Pragmas give hints to the compiler.
Use warnings - Perl complains about variables used only once and improper conversions of strings into numbers. Trying to write to
files that are not opened. It happens at compile time. It is used to
control warnings.
Use strict - declare variables scope. It is used to set some kind of
discipline in the script. If barewords are used in the code they are
interpreted. All the variables should be given scope, like my, our or
local.
The "use strict" directive tells Perl to do extra checking during the compilation of your code. Using this directive will save you time debugging your Perl code because it finds common coding bugs that you might overlook otherwise.
Strict and warnings make sure your variables are not global.
It is much neater to be able to have variables unique for individual methods rather than having to keep track of each and every variable name.
$_, or no variable for certain functions, can also be useful to write more compact code quicker.
However, if you do not use strict and warnings, $_ becomes global!
use strict;
use warnings;
Strict and warnings are the mode for the Perl program. It is allowing the user to enter the code more liberally and more than that, that Perl code will become to look formal and its coding standard will be effective.
warnings means same like -w in the Perl shebang line, so it will provide you the warnings generated by the Perl program. It will display in the terminal.

Can 'use strict' warn instead of error

When using use strict perl will generate a runtime error on unsafe constructs. Now I am wondering if it is possible to have it only print a warning instead of causing a runtime error ? Or is use warnings (or -w) warning about the same issues ?
No, use strict can't be made to issue warnings rather than die. All it does is set a few bits in the magic $^H variable, which triggers various things in the guts of the Perl interpreter.
No, use warnings isn't warning about the same things as use strict kills you for. For instance, use warnings will warn you about variables used only once (which might be the result of typos).
I'm gonna take a stab at guessing the real motivation here. Feel free to tell me if I guessed wrong.
I suspect your trying to tackle a large, older code base and would like to enable strictures but you were hoping first to get a sense of where the errors will be (and how many there are) without breaking functionality. Unfortunately, since use strict functions by modifying the internal behavior of the perl parser and interpreter, there isn't a 'loose strict' or, by analogy to html, any kind of 'transitional' mode.
However, you can tease apart the functionality of use strict to start moving in the right direction. First, note that there are actually three separate parts:
use strict 'refs'; # no symbolic references
use strict 'vars'; # must declare variables
use strict 'subs'; # no barewords
and of those only 'refs' generates runtime errors. So you could easily add use strict qw(vars subs) to each of your files (scripts and modules) and test them with perl -c. If you encounter any error messages, then comment out the use strict, or at least whichever of the two checks failed, and add a comment as to the nature of the failure and move on. This way you can quickly (depending on the number of files) determine which files have compile-time errors and come back to address them later. (If you were more motivated than me at the moment, you could even automate this process). Unless you have code that does scary things inside of BEGIN blocks, this should be pretty safe to do.
The trickier part is checking for the runtime errors generated by use strict 'refs' and unfortunately, there really isn't an easy way to do this because the errors are triggered by symbolic references which can't be determined by any kind of static analysis so -c and/or Perl::Critic are both useless.
Hopefully that gets closer to addressing your real problem.
The warnings and strict pragmas are complementary, not overlapping. The strict pragma has both compile-time and run-time effects. You can't reduce the severity of strictures from errors to warnings, but you can disable them entirely. For example, if you're writing your own export routine you'll need to enable symbolic references in order to manipulate the symbol table.
{
no strict 'refs';
# symrefs okay within this block
}
Warnings can also be disabled lexically (assuming you did use warnings instead of the largely obsolete -w flag).
Strictures and warnings provide a safety net. That's why they're recommended to be used by default. If you disable them you should disable only what's necessary and limit the change to the smallest possible scope.
The preferred method:
use Carp;
sub foo {
croak "no args" unless #_;
}
eval foo();
if( $# ){
print "caught die: $#";
}
If you can't change your die's to croak's:
sub foo {
die "no args" unless #_;
}
{
my $prev_die = $SIG{__DIE__};
$SIG{__DIE__} = sub { print "caught die: $_[0]"; };
eval foo();
$SIG{__DIE__} = $prev_die;
}
The second method will print out the errors on STDERR.
See:
perldoc -f eval
perldoc perlvar and search for /\$\#/ and /__DIE__/
perldoc Carp
Warnings can be made fatal — see perllexwarn — but strict errors can't be made non-fatal.
Why do you want to do that? I suspect an XY problem.