Bracket code section in use strict / no strict? - perl

I inherited some perl code that of course doesn't use either strict or warnings, and I keep using uninitialized variables and the like.
I'd like to bracket the sections of code that I'm modifying like this:
use warnings;
use strict;
... my code changes and additions ...
no strict;
no warnings;
And that seems to work, but I'm having issues deciphering what the perldoc on use means when it says these are compiler directives that import into the current "block scope." Does that mean that any scope can have a use strict unpaired with a no strict? Is the no strict at the tail of the global scope essentially undoing the meaning of use strict earlier in the same scope?

"block scope" means both use strict; and no strict; have effect from where they are to the end of the innermost enclosing block, so no, a later no strict doesn't undo an earlier use strict. It just changes it for the innermost scope from that point in the code on. So:
{
use strict;
# strict in effect
{
# strict still in effect
no strict;
# strict not in effect
}
# strict in effect
no strict;
# strict not in effect
use strict;
# strict in effect
}

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.)

'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.

How to get the set of warning checks currently enabled in the perl module?

In the perllexwarn are defined all warnings what is possible to set.
But here is nothing about, how to print out what warnings i have currently enabled.
E.g.:
use strict;
use warnings;
print warnings::enabled->pretty_print(); #fictional...
How is it possible?
example:
use strict;
use 5.012;
use warnings;
my $aaa;
say "$aaa";
say warnings::enabled("uninitialized") ? "yes" : "no";
The above will output:
Use of uninitialized value $aaa in string at y line 6.
no
so, the "uninitialized" warning category is "set", because its prints a warning, but the warnings::enabled("uninitialized") not returns true.
Reading perllexwarn
... functions that are useful for module authors. These are used when you
want to report a module-specific warning to a calling module has
enabled warnings via the "warnings" pragma.
If I understand it correctly, it means the functions (enabled, warnif) only work for module-specific warnings, not for the standard categories. (There is probably a missing "that" before "has" in the documentation.)
Update: It seems standard categories work as well, but only in a module:
package MY;
use warnings::register;
sub S {
my $x;
print $x, "\t";
print warnings::enabled("uninitialized"),"\n";
}
package main;
use warnings;
MY::S();
no warnings;
MY::S();

Why does strict complain about variables from a required other script?

This is usex.pl:
#use strict;
require 'x.pl';
print $x;
Here is x.pl:
#use strict;
our $x = 99;
1;
It runs fine as shown. If I uncomment the line to use strict in usesx.pl, I get
Global symbol "$x" requires explicit package name
The use or not of strict in x.pl seems not to matter (unless I drop the 'our' keyword, but I'm not interested in that.)
I'm fairly new to Perl. Why does strict make $x not visible in the main script, and what is the normal solution to this?
Two reasons.
The error happens at compile-time, before require is ever executed. That's easy to fix using BEGIN.
our is lexically-scoped, and it's in a different lexical scope (file or block) than the print, so it's no longer in effect.
The whole approach is fundamentally bad. Here's one better way:
package MyConfig;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT = qw( $x );
our $x = 123;
1;
use strict;
use warnings;
use MyConfig;
print "$x\n";
Hehe, our is not easy to grok as it mixes the concepts of global and lexical scope. What it does is exempting a global variable from the strict 'vars' pragma and allowing unqualified access to it within its scope, which is the enclosing block, or the end of the current file, whatever comes first. Read the full (but brief) story in the manual, which is also accessible by saying perldoc -f our on the command line.
As for your script, you can verify the truthfulness of the words in the manual by modifying the variable accessor to use a package-qualified name:
use strict;
require 'x.pl';
print $main::x;

What happens when alternate declaration of Strict pragmas in perl script?

Iam new to perl and trying out a sample code for my project.
What happens when i write a code as given below to enable strict pragmas in perl.
use strict;
....... #Source Code
.......
no strict "vars";
....... #source code
use strict #do all strict pragmas enabled until the next pragma definition ?
......#Source Code
no strict "subs"; #do Only subs strict pragma is disabled and others enabled from here onwards?
...........
Can i embed use Strict Pragma declarations in between source code?
use strict is lexically scoped, which means it will stay in effect "until the end of the enclosing block, file, or eval (whichever comes first)."
For what it’s worth, I think it’s best to isolate the pragma changes using scope:
use strict;
{
no strict;
local $foo = 1;
}
local $bar = 1;
This blows up on setting bar, but not on foo.
From perldoc strict:
If no import list is supplied, all
possible restrictions are assumed.
You can change things to be strict about ("subs", "vars", and "refs") anytime.