Permalink
Browse files

try to fix page generation

  • Loading branch information...
1 parent d4cd391 commit 3d0c5939cc9f673f09f5e115e10b69106ec5c43c @dams committed Sep 16, 2013
Showing with 1 addition and 482 deletions.
  1. +1 −482 _posts/2013-09-16-p5-mop-a-gentle-introduction.markdown
View
483 _posts/2013-09-16-p5-mop-a-gentle-introduction.markdown
@@ -1,6 +1,6 @@
---
layout: post
-title: p5-mop: a gentle introduction
+title: "p5-mop: a gentle introduction"
---
# {{ page.title }}
@@ -16,484 +16,3 @@ implemented in a way that it can be properly included in the Perl core.
Keep in mind that p5-mop goal is to implement a _subset_ of Moose, and. As
Stevan Little says:
-
-> We are not putting "Moose into the core" because Moose is too opinionated,
-> instead we want to put a minimal and less opinionated MOP in the core that is
-> capable of hosting something like Moose
-
-As far as I understood, after a first attempt that failed, Stevan Little
-restarted the p5-mop implementation: the so-called p5-mop-redux
-[github project](https://github.com/stevan/p5-mop-redux), using
-[Devel::Declare](https://metacpan.org/module/Devel::Declare), ( then
-[Parse::Keyword](https://metacpan.org/module/Parse::Keyword) ), so that he can
-experiment and release often, while keeping the implementation core-friendly.
-Once he's happy with the features and all, he'll make sure it finds its way to
-the core. A small team (Stevan Little, [Jesse Luehrs](http://tozt.net/), and
-other contributors) is actively developping p5-mop, and Stevan is regularly
-[blogging about it](http://blogs.perl.org/users/stevan_little/).
-
-If you want more details about the failing first attempt, there is a bunch of
-backlog and mailing lists archive to read. However, here is how Stevan would
-summarize it:
-
-> We started the first prototype, not remembering the old adage of "write the
-> first one to throw away" and I got sentimentally attached to my choice of
-> design approach. This new approach [p5-moop-redux] was purposfully built with
-> a firm commitment to keeping it as simple as possible, therefore making it
-> simpler to hack on.
-> Also, instead of making the MOP I always wanted, I approached as building the
-> mop people actually needed (one that worked well with existing perl classes,
-> etc)
-
-Few months ago, when p5-mop-redux was announced, I tried to give it a go. And
-you should too ! Because it's easy.
-
-## Why is it important to try it out ? ##
-
-It's important to have at least a vague idea of where p5-mop stands at, because
-this project is shaping a big part of Perl's future. IMHO, there will be a
-_before_ and an _after_ having a MOP in core. And it is being designed and
-tested _right_ _now_. So as Perl users, it's our chance to have a look at it,
-test it, and give our feedback.
-
-Do we like the syntax ? Is it powerful enough? What did we prefer more/less
-in Moose ? etc. In few months, things will be decided and it'll only be a
-matter of time and implementation details. Now is the most exciting time to
-participate in the project. You don't need to hack on it, just try it out, and
-provide feedback.
-
-## Install it ##
-
-p5-mop is very easy to install:
-
-0. if you don't have cpanm, get it with `curl -L http://cpanmin.us | perl - App::cpanminus`
-1. first, we need to install twigils, with `cpanm --dev twigils`
-2. if you're using github, just fork the `p5-mop-redux` project. Otherwise you can get a zip [here](https://github.com/stevan/p5-mop-redux/archive/master.zip).
-3. using cpanm, execute `cpanm .` from within the p5-mop-redux directory.
-
-## A first example ##
-
-Here is the classical point example from the [p5-mop test suite](https://github.com/stevan/p5-mop-redux/blob/master/t/001-examples/001-point.t)
-
-{% highlight perl %}
-use mop;
-
-class Point {
- has $!x is ro = 0;
- has $!y is ro = 0;
-
- method set_x ($x) {
- $!x = $x;
- }
-
- method set_y ($y) {
- $!y = $y;
- }
-
- method clear {
- ($!x, $!y) = (0, 0);
- }
-
- method pack {
- +{ x => $self->x, y => $self->y }
- }
-}
-
-# ... subclass it ...
-
-class Point3D extends Point {
- has $!z is ro = 0;
-
- method set_z ($z) {
- $!z = $z;
- }
-
- method pack {
- my $data = $self->next::method;
- $data->{z} = $!z;
- $data;
- }
-}
-{% endhighlight %}
-
-This examples shows how straightforward it is to declare a class and a
-subclass. The syntax is very friendly and similar to what you may find in other
-languages.
-
-`class` declares a class, with proper scoping. `method` is used to define
-methods, so no `sub` there. The distinction is important, because in _methods_,
-additional variables will be automatically available:
-
-* `$self` will be available directly, no need to shift `@_`.
-* attributes variable will be available automatically, so you can access
- attributes from within the class without having to use their
- `$self->accessors`.
-
-Functions defined with the regular `sub` keyword won't have all these features,
-and that's for good: it makes the difference between _function_ and _method_
-more explicit.
-
-`has`declares an attribute. Attribute names are *twigils*. Borrowed from Perl6,
-and implemented by Florian Ragwitz in its
-[twigils project on github](https://github.com/rafl/twigils/), twigils are
-useful to differenciate standard variables from attributes variables:
-
-{% highlight perl %}
-class Foo {
- has $!stuff;
- method do_stuff ($stuff) {
- $!stuff = $stuff;
- }
-}
-{% endhighlight %}
-
-As you can see, it's important to be able to differenciate `stuff` (the
-variable) and `stuff` (the attribute).
-
-The added benefit of attributes variables is that one doesn't need to contantly
-use `$self`. A good proportion of the code in a class is about attributes.
-Being able to use them directly is great.
-
-Other notes worth mentiong:
-* Classes can have a `BUILD` method, as with Moose.
-* A class can inherit from an other one by `extend`-ing it.
-* In a inheriting class, calling the parent method is not done using `SUPER`,
- but `$self->next::method`.
-* A class `Foo` declared in the package `Bar` will be defined as `Bar::Foo`.
-
-## Attributes traits ##
-
-When declaring an attribute name, you can add `is`, which is followed by a list of
-_traits_:
-
-{% highlight perl %}
-has $!bar is ro, lazy = $_->foo + 2;
-{% endhighlight %}
-
-* `ro` / `rw` means it's read-only / read-write
-* `lazy` means the attribute constructor we'll be called only when the
-attribute is being used
-* `weak_ref` enables an attribute to be a weak reference
-
-## Default value / builder ##
-
-{% highlight perl %}
-has $!foo = 'default value';
-{% endhighlight %}
-
-which is actually
-
-{% highlight perl %}
-has $!foo = sub { 'default value' };
-{% endhighlight %}
-
-So, there is no default value, only builders. That means that `has $!foo = {};`
-will work as expected ( creating a new hashref each time ).
-
-You can reference the current instance in the attribute builder by using `$_`:
-
-{% highlight perl %}
-has $!foo = $_->_init_foo;
-{% endhighlight %}
-
-There has been some comments about using `=` instead of `//` or `||` or
-`default`, but this syntax is used in a lot of other programing language, and
-considered somehow the default (ha-ha) syntax. I think it's worth sticking with
-`=` for an easier learning curve for newcomers.
-
-## Methods parameters ##
-
-When calling a method, the parameters are as usual available in `@_`. However
-you can also declare these parameters in the method signature:
-
-{% highlight perl %}
-method foo ($arg1, $arg2=10) {
- say $arg1;
-}
-{% endhighlight %}
-
-Using `=` you can specify a default value. In the method body, these parameters
-will be available directly.
-
-## Types ##
-
-Types are not yet core to the p5-mop, and the team is questioning this idea.
-The concensus is currently that types should not be part of the mop, to keep it
-simple and flexible. You ought to be able to choose what type system you want
-to use. I'm particularly happy about this decision. Perl is so versatile and
-flexible that it can be used (and bent to be used) in numerous environment and
-configuration. Sometimes you need robustness and high level powerful features,
-and it's great to use a powerful typing system like Moose's one. Sometimes
-(most of the time? ) Type::Tiny (before that I used Params::Validate) is good
-enough and gives you faster processing. Sometimes you don't want any type
-checking.
-
-## Clearer / predicate ##
-
-Because the attribute builder is already implemented using `=`, what about
-clearer and predicate?
-
-{% highlight perl %}
-# clearer
-method clear_foo { undef $!foo }
-
-# predicate
-method has_foo { defined $!foo }
-{% endhighlight %}
-
-That was pretty easy, right? Predicates and clearers have been introduced in
-Moose because writing them ourselves would require to access the underlying
-HashRef behind an instance (e.g. `sub predicate { exists $self->{$attr_name}}`)
-and that's very bad. To work around that, Moose has to generate that kind of
-code and provide a way to enable it or not. Hence the `predicate`and `clearer`
-options. So you see that they exists mostly because of the implementation.
-
-In p5-mop, thanks to the twigils, there is no issue in writing predicates and
-cleare ourselves.
-
-But I hear you say "Wait, these are no clearer nor predicate ! They are not testing the
-existence of the attributes, but their define-ness!" You're right, but read on!
-
-## Undef versus not set
-
-In Moose there is a difference between an attribute being unset, and an
-attribute being undef. In p5-mop, there is no such distinction. Technically, it
-would be very difficult to implemente that distinction, because an attribute
-variable is declared even if the attribute has not been set yet.
-
-In Moose, because objects are stored in blessed hashes, an attribute can either
-be:
-
-* non-existent in the underlying hash
-* present in the hash but with an undef value
-* present and defined but false
-* present, defined and true
-
-That's probably too many cases... Getting rid of one of them looks sane to me.
-
-After all, we got this "not set" state only because objects are stored in
-HashRef, so it looks like it's an implementation detail that made its way into
-becoming a concept on its own, which is rarely a good thing.
-
-Plus, in standard Perl programming, if an optional argument is not passed to a
-function, it's not "non-existent", it's _undef_:
-
-{% highlight perl %}
-foo();
-sub foo {
- my ($arg) = @_; # $arg is undef
-}
-{% endhighlight %}
-
-So it makes sense to have a similar behavior in p5-mop - that is, an attribute
-that is not set is undef.
-
-## Roles
-
-Roles definition syntax is quite similar to defining a class.
-
-{% highlight perl %}
-role Bar {
- has $!additional_attr = 42;
- method more_feature { say $!additional_attr }
-}
-{% endhighlight %}
-
-They are consumed right in the class declaration line:
-
-{% highlight perl %}
-class Foo with Bar, Baz {
- # ...
-}
-{% endhighlight %}
-
-## Meta ##
-
-Going meta is not difficult either but I won't describe it here, as I just want
-to showcase default OO programming syntax. On that note, it looks like Stevan
-will make classes immutable by default, unless specified. I think that this is
-a good idea (how many time have you written make_immutable ?).
-
-# My (hopefully constructive) remarks #
-
-## Method Modifiers
-
-Method modifiers are not yet implemented, but they won't be difficult to
-implement. Actually, here is an example of how to implement method modifiers
-using p5-mop very own meta. It implements `around`:
-
-{% highlight perl %}
-sub modifier {
- if ($_[0]->isa('mop::method')) {
- my $method = shift;
- my $type = shift;
- my $meta = $method->associated_meta;
- if ($meta->isa('mop::role')) {
- if ( $type eq 'around' ) {
- $meta->bind('after:COMPOSE' => sub {
- my ($self, $other) = @_;
- if ($other->has_method( $method->name )) {
- my $old_method = $other->remove_method( $method->name );
- $other->add_method(
- $other->method_class->new(
- name => $method->name,
- body => sub {
- local ${^NEXT} = $old_method->body;
- my $self = shift;
- $method->execute( $self, [ @_ ] );
- }
- )
- );
- }
- });
- } elsif ( $type eq 'before' ) {
- die "before not yet supported";
- } elsif ( $type eq 'after' ) {
- die "after not yet supported";
- } else {
- die "I have no idea what to do with $type";
- }
- } elsif ($meta->isa('mop::class')) {
- die "modifiers on classes not yet supported";
- }
- }
-}
-{% endhighlight %}
-
-It is supposed to be used like this:
-
-{% highlight perl %}
-method my_method is modifier('around') ($arg) {
- $arg % 2 and return $self->${^NEXT}(@_);
- die "foo";
-}
-{% endhighlight %}
-
-I would like to see method modifiers in p5-mop. As per Stevan Little and Jesse
-Luehrs, it may be that these won't be part of the mop, but in a plugin or
-extension. I'm not to sure about that, for me method modifier is really linked
-to OO programmning. I prefer using `around` than fiddling with
-`$self->next::method` or `${^NEXT}`.
-
-Here are some syntax proposals I've gathered on IRC and blog comments regarding
-what could be method modifiers in p5-mop:
-
- around foo { }
- method foo is around { ... }
- method foo is modifier(around) { ... }
-
-## ${^NEXT} and ${^SELF}
-
-These special variables are pointing to the current instance (useful when
-you're not in a method - otherwise `$self` is available), and the next method
-in the calling chain. It's OK to have such variables, but their horrible name
-makes it difficult to remember and use.
-
-Can't we have yet an other type of twigils for these variables ? so that we can
-write `$^NEXT` and `$^SELF`.
-
-## Twigils for public / private attributes
-
-Just an idea, but maybe we could have `$!public_attribute` and
-`$.private_attribute`. Or is it the other way around ?
-
-## why `is` ? we already have `has` !
-
-OK this one thing is bothering me a lot: why do we have to use the word `is`
-when declaring an attribute? The attribute declaration starts with `has`. So
-with `is`, that makes it *two* _verbs_ for *one* line of code. For me it's too
-much. in Moo*, the `is` was just one property. we had `default`, `lazy`, etc.
-Now, `is` is just a seperator between the name and the 'traits'. In my opinion,
-it's redundant.
-
-Also, among the new keywords added by p5-mop, we have only _nouns_ (`class`,
-`role`, `method`). Only one _verb_, `has`.
-
-The counter argument on this is that this syntax is inspired by Perl6:
-
-{% highlight perl %}
-class Point is rw {
- has ($.x, $.y);
- method gist { "Point a x=$.x y=$.y" }
-}
-{% endhighlight %}
-
-So, "blame Larry" ? :)
-
-## Exporter
-
-p5-mop doesn't use @ISA for inheritance, so `use base 'Exporter'` won't work.
-You have to do `use Exporter 'import'`. That is somewhat disturbing because
-most Perl developers (I think) implement classes by inheriting from Exporter
-(that's also what the documentation of Exporter recommends).
-
-You could argue that one should code clean classes (that don't export anything,
-and clean modules (that export stuff but don't do OO). Mixing OO in a class
-with methods and exportable subs looks a bit un-orthodox. But that's what we do
-all day long and it is almost part of the Perl culture now. Think about all the
-modules that provides 2 APIs, a functional one and an OO one. All in the same
-namespace. So, _somehow_, being able to easily export subs is needed.
-
-However, as per Jesse Luehrs and Stevan Little, they don't think a MOP
-implementation should be in charge of implementing an Exporter module, and I
-can totally agree with this. So it looks like the solution will be a method
-trait, like `exportable`:
-
-{% highlight perl %}
-sub foo is exportable { ... }
-{% endhighlight %}
-
-But that is not yet implemented.
-
-## Inside Out objects versus blessed structure objects
-
-p5-mop is not using the standard scheme where an object is simply a blessed
-structure (usually a `HashRef`). Instead, it's using InsideOut objects, where
-all you get as an object is some kind of identification number (usually a
-simple reference), which is used internally to retrieve the object properties,
-only accessible from within the class.
-
-This way of doing may seem odd at first: if I recall correctly, there a time
-where InsideOut objects were trendy, especially using `Class::Std`. But that
-didn't last long, when Moose and its follow ups came back to using regular
-blessed structured objects.
-
-The important thing to keep in mind is that it doesn't matter too much. Using
-inside out objects is not a big deal because p5-mop provides so much power to
-interact and introspect with the OO concepts that it's not a problem at all
-that the attributes are not in a blessed HashRef.
-
-However, a lot of third-party modules _assume_ that your objects are blessed
-HashRef. So when switching to p5-mop, a whole little ecosystem will need to be
-rewritten.
-
-# Now, where to ?
-
-Now, it's your turn to try it out, make up your mind, try to port an
-module or write on from scratch using p5-mop, and give your feedback. To do
-that, go to the IRC channel #p5-mop on the irc.perl.org server, say hi,
-and explain what you tried, what went well and what didn't, and how you feel
-about the syntax and concepts.
-
-Also, spread the word by writing about your experience with p5-mop, for
-instance on [blogs.perl.org](blogs.perl.org).
-
-Lastly, don't hesitate to participate in the comments below :) Especially if
-you don't agree with my remarks above.
-
-## Reference / See also
-
-* [p5-mop-redux on github](https://github.com/stevan/p5-mop-redux)
-* [twigils on github](https://github.com/rafl/twigils)
-* [Moose to mop tutorial](https://github.com/stevan/p5-mop-redux/blob/master/lib/mop/manual/tutorials/moose_to_mop.pod)
-* [Moose project homepage](http://moose.iinteractive.com/)
-* [Moops]()
-
-## Contributors
-
-This article has been written by [Damien Krotkine](Damien Krotkine), but these people helped
-proof-reading it:
-* Stevan Little
-* Jesse Luehrs
-* Toby Inkster
-* Lukas Atkinson

0 comments on commit 3d0c593

Please sign in to comment.