PerlDancer/Dancer2 — pull request #628 by JRaspass (2014-07-24 22:30:59+00:00)
Title: Avoid needless sub indirection from DSL keywords.

This is more a RFC as there is an unanswered question on how to identify
functional keywords, POD changes need to be made, and a few more tests of our
DSL would be nice too :-P

So basically, who likes or dislikes this? Is it worth finishing up? What follows is the
commit message as it's rather informative.

---

When importing the DSL keywords into the caller they are currently wrapped in
subs that close over $self like so:

*caller::foo = sub { $self->foo(@_) }

This allows simple calling conventions for the caller. If the keyword has
restrictions on where is can be called from (is_global=0) then this sub is
additionally wrapped like so:

my $code = sub { $self->foo(@_) };

*caller::foo = sub {
croak 'Not from here buddy' unless $self->app->has_request;

$code->(@_);
};

This is wasteful as it creates another layer of indirection. This commit changes
how those DSL keywords are imported like so:

*caller::foo = sub {
croak 'Not from here buddy' unless $self->app->has_request;

$self->foo(@_);
};

There is also a third type of keyword that doesn't need $self at all, these
purely functional keywords can be better imported as:

*caller::foo = $self->can('foo');

This avoids the redirection all together. To identify these keywords is_global
has been set to 2 for those keywords. I'm open to suggestions on this point, I
did toy with the idea of an additional flag, is_functional perhaps?

Another benefit on inlining functional DSL keywords is that by adding prototypes
we can have constant folding applied at compile time like so:

$ perl -Mlib=lib -MDancer2 -MO=Deparse -e 'print dancer_version, true, false'
sub Stream::Buffered::rewind;
sub Stream::Buffered::size;
sub Stream::Buffered::print;
use warnings;
use strict;
print dancer_version(), 1, 0;
-e syntax OK

The calls to true and false have been completely inlined whereas the call to
dancer_version can't be as Dancer2->VERSION is not a constant.

Furthermore this commit tweaks how subs are aliased in Dancer2, preferring the
more efficient "*alias = \&sub" form wherever possible.

One point of note is that export_symbols_to no longer returns a list of what it
has imported, the two and only calls to this don't seem to make use of this so I
can't see it being a huge issue but it could be made to work if needed.