develooper Front page | perl.perl5.porters | Postings from March 2000

module warnings - a discussion

From:
Marquess,P,Paul,NEL38 R
Date:
March 5, 2000 13:13
Subject:
module warnings - a discussion
Message ID:
5104D4DBC598D211B5FE0000F8FE7EB2067FE563@mbtlipnt02.btlabs.bt.co.uk
Health Warning -- I realise we are very close to 5.6, so anything discussed
here is too late to make the cut.

I've been thinking about the functionality I added to allow modules to peek
at the warnings bitmask that the calling module uses. Whilst I'm happy with
the concept as it is currently implemented, I think it needs to be taken a
bit further.

For example, at the moment you can do this

    package Fred ;

    no warnings;

    sub doit
    {
      if ($_[0] =~ /\n/ && warnings::enabled("newline") )
       { warnings::warn("newline", "newline found in filename") }
    }

    1 ;

So when a calling module uses package Fred like this

    use warnings 'all' ;
    use Fred ;
    Fred::doit("abc\ndef")

the Fred::doit function can detect that the "newline" category is enabled in
the calling module and display an appropriate warning. In this particular
example, the "newline" category is an appropriate choice for the warning
message. The thing I noticed when I looked at the warnings that the core
modules produced was that they were very specific to the modules themselves.

For example, this is from constant.pm

    if ($^W) {
        require Carp;
        if ($keywords{$name}) {
            Carp::carp("Constant name '$name' is a Perl keyword");
        } elsif ($forced_into_main{$name}) {
            Carp::carp("Constant name '$name' is " .
                "forced into package main::");
        } elsif (1 == length $name) {
            Carp::carp("Constant name '$name' is too short");
        } elsif ($name =~ /^_?[a-z\d]/) {
            Carp::carp("Constant name '$name' should " .
                "have an initial capital letter");
        } else {
            # Catch-all - what did I miss? If you get this error,
            # please let me know what your constant's name was.
            # Write to <rootbeer@redcat.com>. Thanks!
            Carp::carp("Constant name '$name' has unknown problems");
        }
    }                      

The only existing category that would be appropriate for these warnings is
the catch-all "misc" category. Sure, for this particular module we could,
and probably should, create a "constant" category. But that is because it
part of the core. It doesn't help the modules that only exist on CPAN or
modules that never make it into the public domain.

Another possibility, which I've been thinking about, is to allow modules to
optionally register their own warning category name, rather than piggyback
the existing set. To keep things simple I was thinking that the category
name registered would always match the module name. So, for example,
File::Path could only register a category called "File::Path". 

Here is the Fred module from the start rewritten to use this hypothetical
new functionality.

    package Fred ;

    use warnings::register ;

    sub new
    {
      if ($_[0] =~ /\n/ && warnings::enabled_self() )
       {warnings::warn_self("newline found in filename")}
    }

    1 ;

The call to warnings::register creates a new warnings category called
"Fred". The warnings::enabled_self and warnings::warn_self functions are
"smart" versions of warnings::enabled and warnings::warn respectively. The
only difference between the two new functions and the existing ones is that
the new ones know which module they are running in and automatically set the
category name appropriately. By the way, I just thought up the *_self names
for the purposes of this message. I'm sure better ones can be found.

This is how a user would call this code

    use Fred ;
    use warnings 'Fred' ;
    Fred::doit("abc\ndef")

It's worth noting that if the first two lines above are swapped, the code
will silently do the wrong thing and not display the warning.

    use warnings 'Fred' ;
    use Fred ;
    Fred::doit("abc\ndef")

That's because when the warnings pragma is called with "Fred", that category
name won't yet exist, so the warnings bitmask will be unchanged. It does get
created on the next line, but that's too late. Someone patched the warnings
pragma a while back to silently ignore unknown categories because that is
what the other pragmas tend to do. If this feature, or something like it,
does ever get added, it might be an idea to make the use of non-existent
category names a fatal error. 

At the moment this is just an idea I'm thinking through. I haven't written
any code for it at all. The big problem with implementing something like
this is that the size of the warnings bitmask will not be a constant for
each compiled line of code (as it is now), but it will increase the further
you get into the compilation. I haven't yet thought through all the issues
with this, so it may end up being too expensive to implement.

Before I take this any further I would appreciate some comments from the
group. Is this a feature that would be useful enough to have? and more
importantly, would you actually use it?

Paul



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About