NAME
Python::Decorator - Function composition at compile-time
SYNOPSIS
This code:
use Python::Decorator;
[...]
# add memoization to incr(). note the python-ish syntax with the
# absence of ';' after the decorator
@memoize
sub incr {
return $_[0]+1;
}
is really just the same as this one:
{
no strict 'refs';
*{__PACKAGE__."::incr"} = memoize(
sub { return $_[0]+1; }
);
}
In fact, the syntax:
@memoize
sub incr {
reads as: "before compiling incr()
, redefine incr()
to be the function resulting from the composition of the function returned by memoize()
applied to incr()
".
The function memoize()
takes a function to decorate and returns the new decorated function.
As in Python, you can pass arguments to the decorator:
@mylog("incr") # log calls to incr()
sub incr {
return $_[0]+1;
}
becomes:
{
no strict 'refs';
*{__PACKAGE__."::incr"} = mylog("incr")->(
sub { return $_[0]+1; }
);
}
Notice that a decorator that takes arguments does not behave in the same way as one that takes no arguments. In the case above, the function mylog()
takes some arguments and returns a new no-argument decorator, ie a function that takes a function to decorate and returns the new decorated function. Though surprising at first, this behavior is the same as in Python.
As in Python, you can apply multiple decorators to one subroutine:
# replace incr by proxify(mylog(memoize(incr)))
@proxify
@mylog("incr")
@memoize
sub incr {
return $_[0]+1;
}
becomes:
{
no strict 'refs';
*{__PACKAGE__."::incr"} = proxify(mylog("incr")->(memoize(
sub { return $_[0]+1; }
)));
}
Finally, if you want to see what Python::Decorator really does to the source, call it with:
use Python::Decorator debug => 1;
DESCRIPTION
Decorators are syntax sugar for function composition at compile-time.
Decorators were introduced in Python 2.4 (end of 2004) and have proven since to provide functionality close to that of LISP macros. For a complete description of decorators, ask google.
Python::Decorator implements the decorator syntax for Perl5, using exactly the same syntax as in Python. It is a source filter, meaning it manipulates source code before compilation. Decorated subroutines are therefore composed at compile-time.
This module is a proof-of-concept in at least 2 ways:
There is no consensus as to which syntax macros or function composition should have in Perl. Therefore Python::Decorator implements decorators using Python's own syntax instead of trying to introduce a more perlish syntax. If this module proves usefull, someone will have to clone it into something more perlish.
This module experiments using PPI to parse Perl5 source code within a source filter. Though this is a slow and somewhat unstable technic, I believe it's a way to go to get macros working in Perl.
API
Those functions are for internal use only:
import
Implementsimport
as required by Filter::Util::Call.filter
Implementsfilter
as required by Filter::Util::Call.
WARNING
Use in production code is REALLY NOT RECOMMENDED!
SEE ALSO
See PPI, Filter::Util::Call, Aspect.
BUGS
See PPI. Otherwise, report to the author!
VERSION
$Id: Decorator.pm,v 1.4 2008-11-05 14:12:43 erwan Exp $
AUTHORS
Erwan Lemonnier <erwan@cpan.org>
.
LICENSE
This code is provided under the Perl artistic license and comes with no warranty whatsoever.