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.
Undefined subroutine &main::foo ...
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...
use strict
Version 1.10, 14-Oct-2008.
use ensure ;
which, in a package, is intended to replace:
use Exporter qw(import) ;
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.
use ensure
CHECK
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:
ensure::import
Exporter::import
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.)
:ALL
:NONE
:IMPLICIT
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.
use ensure ()
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.
no ensure
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.
fred()
our
my
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(...).
sub freda
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.
SCALAR
undef
$fred
fred
[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:
\w
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.
ensure
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
Any package (our) SCALAR variables in main need to be declared no ensure (unless assigned a value in a BEGIN block).
BEGIN
[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 examine the exporting package's @EXPORT, @EXPORT_OK, %EXPORT_TAGS and @EXPORT_FAIL to ensure that:
@EXPORT
@EXPORT_OK
%EXPORT_TAGS
@EXPORT_FAIL
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).
IMPLICIT
DEFAULT
The import list extensions are:
: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).
:DEFAULT
If the result is an empty list, then Exporter::import will not be invoked !
It is slightly clearer than !:DEFAULT, though essentially equivalent.
!:DEFAULT
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.
!:NONE
NONE
: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.
!:ALL
ALL
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:
EXPORTS
use Foo () ; -- imports nothing. Foo-<gtimport> is not called at all.
use Foo () ;
Foo-<gt
use Foo qw(a ...) ; -- explicitly imports only the named items.
use Foo qw(a ...) ;
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.
@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.
!:IMPLICIT
Any package that uses IMPLICIT should advertise the fact clearly.
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.
Exports import. Suggest replacing use Exporter qw(import) ; by use ensure ;.
import
ensure::register(package) may be used to register a given package for ensure CHECK block processing.
ensure::register(
)
ensure CHECK
Generates various warn messages when it finds:
warn
'name' in 'package' is declared 'no ensure', but is defined
'
' in '
' is declared 'no ensure', but is defined
'name' is exported by 'package' but is not defined
' is exported by '
' but is not defined
'name' is in 'package's %EXPORT_TAGS, but not in @EXPORT or @EXPORT_OK
' is in '
's %EXPORT_TAGS, but not in @EXPORT or @EXPORT_OK
'name' is in 'package's IMPLICIT tag list, but not in @EXPORT
's IMPLICIT tag list, but not in @EXPORT
'name' is in 'package's @EXPORT_FAIL, but not in @EXPORT or @EXPORT_OK
's @EXPORT_FAIL, but not in @EXPORT or @EXPORT_OK
'package::name' is undefined
::
' is undefined
If any such warnings are issued, the ensure CHECK will die once all registered packages have been checked:
die
n ensure errors
ensure errors
The ensure::import function uses the Exporter::import function.
None known, but tested only on Perl v5.8.8 and v5.10.0.
None known.
Chris Hall <chris.hall@highwayman.com>
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.
To install ensure, copy and paste the appropriate command in to your terminal.
cpanm
cpanm ensure
CPAN shell
perl -MCPAN -e shell install ensure
For more information on module installation, please visit the detailed CPAN module installation guide.