The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

ensure - Perl extension to ensure that things, particularly subroutines, are defined before a program runs -- to avoid being bitten by Undefined subroutine &main::foo ... run-time errors.

use strict will find undefined variables, but not undefined subroutines (except for bareword subroutine references). You could argue that use strict is incomplete, and I wouldn't disagree. But in the meantime...

VERSION

Version 1.10, 14-Oct-2008.

SYNOPSIS

   use ensure ;

which, in a package, is intended to replace:

   use Exporter qw(import) ;

DESCRIPTION

The objective of the ensure package is to ensure that things are defined before a program runs:

  • check for undefined subroutines before program runs (as far as possible).

  • check exports are defined when package is used.

First, use ensure creates an CHECK block to check that registered packages are "complete": looks for names which have no part defined -- probably as the result of a missing subroutine definition or a misspelling of a subroutine name.

All packages which use ensure are registered for this check.

Second, use ensure imports the ensure::import function. This sits on top of the Exporter::import function, and has two effects:

  • the first time the package is itself used, the package's exports are checked. (See below for what is checked).

  • every time the package is used the import list extensions (:ALL, :NONE & :IMPLICIT) are implemented, before jumping to the standard Exporter::import. (See below for what these extensions do.)

Packages that use ensure do not need to import the Exporter::import (and must not).

NB: it would be perverse to use ensure (), because that inhibits all of the above.

no ensure may be used to declare things which are not expected to be defined when the CHECK block checks and the export checks are run.

The CHECK block check

The check scans the registered packages' symbol tables, looking for names which have no part defined. This will find most undefined subroutines.

However, a reference to an undefined subroutine, eg fred(), can be masked by any other package (our) variable of the same name -- but not by private (my) variables.

This means that:

   sub freda { .... } ;
   sub bill {
     ...
     fred(...) ;
     ...
   } ;

will be generally be picked up, trapping (a) a missing definition for fred(), or (b) a spelling mistake in sub freda, or (c) a spelling mistake in fred(...).

However the presence of (for example):

   our @fred ;

will mask the use of the undefined subroutine fred(), so the error is not trapped.

The effect of:

   our $fred ;

is more complicated, because in the special case of SCALAR variables, it is not possible to tell the difference between a variable that has not been defined at all, and a variable that has been defined but whose value is undef. So, if the value of $fred is undef when the CHECK block is run, it will not mask the presence of an undefined subroutine fred, but it will if it has any other value.

[This could be improved if I knew how to spot subroutine names that have been used, but not defined.]

The check ignores names that contain any characters other than letters, digits or '_' (ie \w), and names that start with a digit or more than one '_'. It also ignores a number of names which appear in package symbol tables and are often undefined:

    a  b
    BEGIN  UNITCHECK  CHECK  INIT  END  DESTROY  AUTOLOAD
    MODIFY_SCALAR_ATTRIBUTES  MODIFY_ARRAY_ATTRIBUTES  MODIFY_HASH_ATTRIBUTES

this stops ensure from throwing out "system" things.

The Perl debugger adds a number of things to module main's symbol table, some of which appear undefined when the check runs. To avoid being obstructive, the check is suppressed for main when the debugger is detected, and a warning issued.

main package SCALAR variables

Any package (our) SCALAR variables in main need to be declared no ensure (unless assigned a value in a BEGIN block).

[This could be improved if I knew how to spot scalars that have been declared but are yet to be assigned a value.]

The export checks

The export checks examine the exporting package's @EXPORT, @EXPORT_OK, %EXPORT_TAGS and @EXPORT_FAIL to ensure that:

  • everything in @EXPORT and @EXPORT_OK is defined by the time the package is first used -- or declared no ensure.

    This check for definition might have been left to the ensure CHECK block. However, it seems that Exporter::import manages to define things, even if there is no mention of them in the package itself -- so it is essential to check before the first use of Exporter::import.

  • everything in %EXPORT_TAGS and in @EXPORT_FAIL must appear in either @EXPORT or @EXPORT_OK.

  • if there is a IMPLICIT tag in %EXPORT_TAGS, everything in that tag must appear in @EXPORT (ie IMPLICIT must be a subset of DEFAULT).

The import list extensions

The import list extensions are:

  1. :NONE pseudo tag

    This is expected to be the only item in the import list. In any case it should be the first item.

    The purpose of the :NONE tag is to allow for nothing to be imported, while still invoking the ensure::import function to implement the export checks.

    When the import list is processed, if the first tag is :NONE it is removed, along with any following '!' items (which are redundant, and would otherwise pull in the :DEFAULT set).

    If the result is an empty list, then Exporter::import will not be invoked !

    It is slightly clearer than !:DEFAULT, though essentially equivalent.

    NB: !:NONE has no meaning and will generate an error (unless an actual NONE tag exists in %EXPORT_TAGS). Similarly :NONE as second or subsequent item.

  2. :ALL pseudo tag

    If the first item in the import list is :ALL, it will be replaced by the entirity of @EXPORT and @EXPORT_OK.

    NB: !:ALL has no meaning and will generate an error (unless an actual ALL tag exists in %EXPORT_TAGS). Similarly :ALL as second or subsequent item.

  3. IMPLICIT tag -- specifies a minimum, required set of imports/exports.

    When a package is used the items named in @EXPORTS (aka the :DEFAULT exports) are automatically exported, except for:

    1. use Foo () ; -- imports nothing. Foo-<gtimport> is not called at all.

    2. use Foo qw(a ...) ; -- explicitly imports only the named items.

    If the exporting package has some subset of the :DEFAULT exports which it wants to export even in case (2), then it can add an IMPLICIT tag to %EXPORT_TAGS, containing that subset of @EXPORTS.

    If the importing package requires the absolute minimum of imports it can do:

       use Foo qw(:IMPLICIT) ;

    Note that :IMPLICIT can appear as the first tag even if the package has no IMPLICIT tag, and will behave as if there was an empty IMPLICIT tag.

    Note that :NONE will import nothing, not even :IMPLICIT stuff.

    NB: !:IMPLICIT has no meaning and will generate an error (unless an actual IMPLICIT tag exists in %EXPORT_TAGS). Similarly :IMPLICIT as second or subsequent item.

    Any package that uses IMPLICIT should advertise the fact clearly.

no ensure

Names may be declared as no ensure, thus:

   no ensure qw(a $a @a %a &a *a ...)

A package may contain a number of no ensure declarations, each adding to its list of no ensure names.

For the CHECK block the decoration is ignored. Any name declared in no ensure is not checked when the relevant package is checked.

For the export check the decoration is significant. It is not an error to export something which is undefined if that something is declared no ensure. On the other hand, it is an error to export something which is defined but is also declared no ensure.

EXPORT

Exports import. Suggest replacing use Exporter qw(import) ; by use ensure ;.

SUBROUTINES/METHODS

ensure::register(package) may be used to register a given package for ensure CHECK block processing.

DIAGNOSTICS

Generates various warn messages when it finds:

  • 'name' in 'package' is declared 'no ensure', but is defined

  • 'name' is exported by 'package' but is not defined

  • 'name' is in 'package's %EXPORT_TAGS, but not in @EXPORT or @EXPORT_OK

  • 'name' is in 'package's IMPLICIT tag list, but not in @EXPORT

  • 'name' is in 'package's @EXPORT_FAIL, but not in @EXPORT or @EXPORT_OK

  • 'package::name' is undefined

If any such warnings are issued, the ensure CHECK will die once all registered packages have been checked:

  • n ensure errors

DEPENDENCIES

The ensure::import function uses the Exporter::import function.

INCOMPATIBILITIES

None known, but tested only on Perl v5.8.8 and v5.10.0.

BUGS AND LIMITATIONS

None known.

AUTHOR

Chris Hall <chris.hall@highwayman.com>

LICENSE AND COPYRIGHT

Copyright (C) 2008 by Highwayman Associates Ltd. All rights reserved

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.