My Favorite Warnings — A Belated Introduction

Look, that's why there's rules, understand? So that you think before you break 'em. — Terry Pratchett, in Thief of Time.

A couple installments into this series of blog posts, I realized an introduction to Perl warnings would be appropriate, with some words on how to turn them off, and why you probably do not want to. Yes, this should have been the first post in the series, but I didn't know it would actually be a series, and, well, maybe better late than never.

The Perl compiler/interpreter can emit warnings when it finds things that may indicate a problem with the code. These are not (yet) enabled by default, but experience has shown that enabling them can highlight conceptual and logic errors.

Back in the early days of Perl 5, these were enabled using the -w command-line option, or by setting the $^W variable to a true value. But this mechanism had two drawbacks: it was all-or nothing, and it was global in scope. Certainly the value of $^W could be localized, but localization does not prevent a called module from seeing changes made by its caller.

The warnings pragma, first released in Perl 5.6.0, addresses both these problems. As of Perl 5.34.0 it provides 75 warning categories which can be specified individually. Unfortunately the documentation for this pragma contains only the names of the categories; their descriptions are mixed into perldiag.

Because it is a pragma, the effects of use warnings; are lexical in scope: from the point of use to the most-local enclosing right curly bracket (or the end of the file if none), but not leaking into called modules.

use warnings; (without listing any warning categories) enables all warnings. The warnings have proven so useful that this line of Perl is extremely common boilerplate at or near the beginning of a Perl source file. This might actually be the default behavior by now, except for concern about the effect on legacy code.

For example: a Perl scalar can take on an undefined value (undef), and in fact it has this value when first created. The results of operating on the undefined value are well-defined: the empty string in string context, zero in numeric context, and false in Boolean context. But since undef is the default value, if you try to operate on it, is the attempt deliberate, or did you forget to assign a value (or assign it to the wrong variable)? Perl can not resolve this, so the safe thing is to issue a warning, and let the programmer figure it out.

The thing is, maybe the programmer intended to make use of this behavior, in which case the warning is unwanted noise, and needs to be turned off. No problem: no warnings 'uninitialized'; is the Perlish way to say "I meant to do that!" in this circumstance.

And now we come to the point of the quote that started this post: just because you can turn off a specific warning (or all of them) does not mean that you should, at least not without understanding why it is generated and why it is or is not relevant to your case. If you do elect to turn off a warning, it is best to turn it off in the smallest practical scope. After all, it is the nature of code to grow; disabling warnings in a larger scope provides more places for changes to introduce bugs — bugs that Perl's warnings might have alerted you to had they not been disabled. Caveat coder.

Previous entries in this series:

  1. once
  2. redundant and missing
  3. exiting

Leave a comment

About Tom Wyant

user-pic I blog about Perl.