home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Perl CookbookPerl CookbookSearch this book

12.15. Customizing Warnings

12.15.3. Discussion

Perl's -w command-line flag, mirrored by the global $^W variable, suffers from several problems. For one thing, it's an all-or-nothing affair, so if you turn it on for the program, module code included by that program—including code you may not have written—is also affected by it. For another, it's at best cumbersome to control compile-time warnings with it, forcing you to resort to convoluted BEGIN blocks. Finally, suppose you were interested in numeric warnings but not any other sort; you'd have to write a $SIG{_ _WARN_ _} handler to sift through all warnings to find those you did or did not want to see.

Lexical warnings, first introduced in Perl v5.6, address all this and more. By lexical, we mean that their effects are constrained to the lexical scope in which use warnings or no warnings occurs. Lexical warnings pay no attention to the -w command-line switch. Now when you turn warnings on in one scope, such as the main program's file scope, that doesn't enable warnings in modules you load. You can also selectively enable or disable individual categories of warnings. For example:

use warnings qw(numeric uninitialized);

use warnings qw(all);
no warnings qw(syntax);

The warnings::register pragma permits a module to check the warnings preferences of its caller's lexical scope. The pragma also creates a new warning category, taken from the name of the current package. These user-defined warning categories are easily distinguishable from the built-in warning categories because a module's package always starts (or should always start) with an uppercase letter. This way lowercase warning categories, like lowercase module names, are reserved to Perl itself.

Built-in warnings categories are organized into several groups. The all category means all built-in warnings categories, including subcategories such as unsafe, io, syntax, etc. (see Figure 12-1). The syntax category comprises particular warnings categories, such as ambiguous, precedence, and deprecated. These can be added and subtracted at will, but order matters:

Figure 12-1

Figure 12-1. Warnings categories

use warnings;                 # turn on all warnings
no  warnings "syntax";        # turn off the syntax group
use warnings "deprecated";    # but turn back on deprecated warnings

Back to your module. Suppose you write a module called Whiskey. The Whiskey.pm file begins this way:

package Whiskey;
use warnings::register;

Now code using that module does this:

use Whiskey;
use warnings qw(Whiskey);

It's important to load the module before asking to use warnings for that module. Otherwise, the Whiskey warning category hasn't been registered yet, and you'll raise an exception if you try to use it as a warnings category.

Here's a whimsical Whiskey module:

package Whiskey;

use strict;
use warnings;  # for our own code, not our caller
use warnings::register;

sub drink {
    if (warnings::enabled( ) && (localtime( ))[2] < 12) {
        warnings:warn("Sun not yet over the yardarm");
    } 
    print "Merry!\n";
} 
sub quaff {
    if (warnings::enabled("deprecated")) {
        warnings::warn("deprecated", 
            "quaffing deprecated in favor of chugging");
    } 
    &drink;
} 
# chuggers care not of the hour
sub chug {
    print "Very merry\n";
} 
1;

The Whiskey::drink function uses the warnings::enabled function to check whether its caller has warnings enabled. Any of these in the caller's scope is enough to make that function return true:

use warnings;
use warnings qw(all);  # means same as previous
use warnings qw(Whiskey);

The function will also return true if global warnings are enabled using -w or $^W.

In the Whiskey::quaff function, a specific category of warnings is checked: deprecated. This is enabled if all warnings have been selected, if the syntax warnings have been selected (because deprecated warnings are considered a subcategory of syntax warnings, which is a subcategory of all warnings), or if deprecated warnings have been specifically selected. It will not be enabled just because the caller has enabled Whiskey warnings. Any category you create is considered a subcategory of all, but not of anything else. Check for Whiskey warnings using:

warnings::enabled("Whiskey")

The warnings::warn function is used instead of the warn built-in, in case Whiskey warnings have been promoted into exceptions:

use warnings FATAL => "Whiskey";


Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.