Customizing Warnings (Perl Cookbook, 2nd Edition)

## 12.15. Customizing Warnings

### 12.15.1. Problem

You would like your module to respect its caller's settings for lexical warnings, but you can't inspect the predefined `$^W`[22] variable to determine those settings.

> [22]That's `$WARNING` if you've `use` d English.

### 12.15.2. Solution

Your module should use this pragma:

>     use warnings::register;

Then from inside your module, use the `warnings::enabled` function from that module as described in the Discussion to check whether the caller has warnings enabled. This works for both the old-style, global warnings and for lexical warnings set via the `use` `warnings` pragma.

### 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. 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";

### 12.15.4. See Also

The documentation on the `use warnings` pragma in Chapter 31 of Programming Perl and perllexwarn(1)

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