NAME
Sub::Attribute::Prototype - polyfill for :prototype attribute on older
perls
SYNOPSIS
use Sub::Attribute::Prototype;
sub afunc :prototype(&@) {
...
}
DESCRIPTION
This polyfill allows a module to use the :prototype function attribute
to apply a prototype to a function, even on perls too old to natively
support it.
Perl version 5.20 introduced the :prototype attribute, as part of the
wider work surrounding subroutine signatures. This allows a function to
declare a prototype even when the use feature 'signatures' pragma is in
effect.
If a newer version of perl switches the defaults to making signature
syntax default, it will no longer be possible to write prototype-using
functions using the old syntax, so authors will have to use :prototype
instead. By using this polyfill module, an author can ensure such
syntax is still recognised by perl versions older than 5.20.
When used on a version of perl new enough to natively support the
:prototype attribute (i.e. 5.20 or newer), this module does nothing.
Any :prototype attribute syntax used by the user of this module is
simply handled by core perl in the normal way.
When used on an older version of perl, a polyfilled compatibility
attribute is provided to the caller to (mostly) perform the same work
that newer versions of perl would do; subject to some caveats.
Caveats
The following caveats should be noted about the pre-5.20 polyfilled
version of the :prototype attribute.
* Due to the way that attributes are applied to functions, it is not
possible to apply the prototype immediately during compiletime.
Instead, they must be deferred until a slightly later time. The
earliest time that can feasibly be implemented is UNITCHECK time of
the importing module.
This has the unfortunate downside that function prototypes are NOT
visible to later functions in the module itself, though they are
visible to the importing code in the usual way. This means that
exported functions will work just fine from the perspective of a
module that uses them, they cannot be used internally within the
module itself.
Because this limitation only applies to the polyfilled version of the
attribute for older versions of perl, it means the behavior will
differ on a newer version of perl. Thus it is important that if you
wish call a prototyped function from other parts of your module, you
must use the prototype-defeating form of
my $result = &one_of_my_functions( @args )
in order to get reliable behaviour between older and newer perl
versions.
* Perl versions older than 5.20 will provoke a warning in the
reserved category when they encounter the attribute syntax provided
by this polyfill, even though the polyfill has consumed the
attribute. In order not to cause this warning to appear to users of
modules using this syntax, it is necessary for this polyfill to
suppress the entire reserved warning category. This means that all
such warnings will be silenced, including those about different
attributes.
* Because core perl does not have a built-in way for exporter to
inject a UNITCHECK block into their importer, it is necessary to use
a non-core XS module, B::CompilerPhase::Hook, to provide this. As a
result, this polyfill has non-core depenencies when running on older
perl versions, and this dependency includes XS (i.e. compiled) code,
and is no longer Pure Perl. It will not be possible to use tools such
as App::FatPacker to bundle this dependency in order to ship a
pure-perl portable script.
It should be stressed that none of these limitations apply when running
on a version of perl 5.20 or later. Though in that case there is no
need to use this polyfill at all, because the :prototype attribute will
be natively recognised.
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>