flickr: philip66
Make your own Perl
with
M o o p s
@friedo
Mike Friedman
London Perl Workshop 2014
A brief history…
A brief history…
In the Beginning,
Perl 5
was already extensible.
use Foo qw(bar);
use Foo qw(bar);
BEGIN {!
require Foo;!
Foo->import( ‘bar’ );!
};
How does
!
import!
!
actually work?
sub import {!
my $pkg = shift;!
...
a typical import sub
sub import {!
my $pkg = shift;!
my $callpkg = caller;!
...
a typical import sub
sub import {!
my $pkg = shift;!
my $callpkg = caller;!
my @imports = @_;!
...
a typical import sub
sub import {!
... !
foreach !
my $sym(@imports) {!
*{"${callpkg}::$sym"}
= *{"${pkg}::$sym"}
a typical import sub
(many details omitted.)
A brief history…
import is compile-time.
A brief history…
import is compile-time.
1. add functions.
2. pretend they’re keywords.
package Adder;!
!
sub import { ... }!
sub add2 { !
return shift + 2;!
}
a pretend keyword
package Mine;!
!
use Adder;!
!
say add2 42;
a pretend keyword
A brief history…
Perl 5.2
!
Prototypes
Make fake keywords
!
That behave like
builtins
(kinda)
sub doblock(&@) { !
my $blk = shift;!
return $blk->( @_ );!
}!
!
doblock { !
say $_ * $_ for @_;!
} ( 1, 2, 3, 4, 5 );!
a prototype pretend keyword
sub doblock(&) { ... }!
!
doblock { !
say "first";!
}!
!
say "second";
a prototype pretend keyword
sub doblock(&) { ... }!
!
doblock { !
say "first";!
}!
!
say "second";
a prototype pretend keyword
# Fail :(
Prototype subs only
work as expressions.
!
Not statements.
sub doblock($&) { ... }!
!
doblock name { !
say "first";!
}!
!
a prototype pretend keyword
# Fail :(
a prototype pretend keyword
# We have to say:
!
!
doblock name => sub { !
say "first";!
};!
!
a prototype pretend keyword
# We have to say:
"&" prototypes are only
magical if they're first.
A brief history…
Perl 5.8
!
Devel::Declare
The first real way to add
!
new syntax.
use MooseX::Declare;!
!
class Foo { !
method bar { ... }!
...!
}!
!
a parser magic keyword
Devel::Declare is
complicated
Devel::Declare is
complicated
•Declarators?
Devel::Declare is
complicated
•Declarators?
•Scope injectors?
Devel::Declare is
complicated
•Declarators?
•Scope injectors?
•Method shadowing?
Devel::Declare is
complicated
•Declarators?
•Scope injectors?
•Method shadowing?
•WTF?
MooseX::Declare is
big, slow, and difficult to
extend.
A brief history…
Perl 5.12
!
The keyword API
Real keyword interface
in the
Perl core API.
package My::Keyword;!
use Keyword::Simple;!
!
sub import { !
Keyword::Simple::define( !
class => sub { !
munge_code( $$_[0] );!
}!
);!
a real custom keyword
So...
!
what is
!
M o o p s ?
use Moops;!
role NamedThing {!
has name => !
(is => "ro", isa => Str);!
}!
!
class Person with NamedThing;!
...
a Moops-defined class
So it's like
MooseX::Declare
?
Not exactly.
Not exactly.
•Moo by default, but can use Moose
Not exactly.
•Moo by default, but can use Moose
•Uses Keyword::Simple for new syntax.
Not exactly.
•Moo by default, but can use Moose
•Uses Keyword::Simple for new syntax.
•Uses Kavorka for functions/methods
Not exactly.
•Moo by default, but can use Moose
•Uses Keyword::Simple for new syntax.
•Uses Kavorka for functions/methods
•Designed for easy extensibility
A brief history…
One year ago,
!
I did this:
I like imports
I hate boilerplate
package MyApp::Setup;!
use Import::Into;!
!
use List::Util ();!
use List::MoreUtils ();!
use Scalar::Util ();!
use Const::Fast ();!
use Try::Tiny ();!
use Data::Alias ();!
use autodie ();!
...
Custom setup class
!
!
sub import { !
my $callpkg = caller;!
Scalar::Util->import::into(!
$callpkg, 'blessed', 'refaddr'!
);!
List::Util->import::into(!
$callpkg, 'reduce', 'all', ...!
);!
...!
}
Custom setup class
Works pretty great!
Unless I want to use
custom syntax
use MooseX::Declare; !
# (or Moops)!
!
class MyApp::Thing { !
use MyApp::Setup;!
}!
!
# :/!
Custom setup class
I have to use the Setup
class from within
the right namespace.
What if the Setup class
could also inject custom
syntax?
package MyApp::Setup;!
use parent 'Moops';!
sub import { !
my $pkg = shift;!
my @imports = (!
'List::Util' => ['any'],!
'Scalar::Util' => ['blessed'],!
'experimental' => ['postderef']!
...!
);!
}
Moops-based setup class
sub import {!
...!
$pkg->SUPER::import(!
imports => @imports!
);!
}!
!
!
# :D
Moops-based setup class
Cool!
flickr: philip66
Questions
@friedo
Mike Friedman
London Perl Workshop 2014

Make Your Own Perl with Moops