Notes on porting to p5-mop
Just a follow-up to Stevan Little's On porting a Moose module (thanks Stevan, BTW for this software! :) I read Damien Krotkine's p5-mop: a gentle introduction yesterday, so I took p5-mop out for a spin and started porting my Hashids module to it; Hashids itself is a port of the JavaScript hashids.js library from Ivan Akimov, and provides an easy way of creating "hashes" of alphanumeric strings similar to the ones used in YouTube.
Here are a few things I observed while doing the port, which I'm glad to say, was a very easy and worthwhile thing to do (if at least to help me think about improving my own use of Perl:)
- Porting wasn't hard, especially coming from Moo*: when I started writing my module, I had just read the new perlootut from perldoc, and decided that my new OO modules from now on would be made using Moo. If p5-mop gets into core, I'll probably decide later to switch to it fully, for stuff that target perl v5.20+
- Learning p5-mop isn't hard: the docs are still mostly unwritten (and I feel this will be fixed soon,) but the tests seem solid enough to start getting an idea of how p5-mop works. Furthermore, the fine people in #p5-mop can help clear up stuff along the way. Indeed, part of the reason for this exercise is also to get some stuff down to writing, like this post, and contribute it later to the official documentation.
No need forPut apackage
package main;
line in a one-class module;if you have a simple top-level class name like this module, you can get away with not adding arecent versions of p5-mop now qualify classes as packages. Edit: doy on #p5-mop suggests putting a package line nevertheless, to ensure that the class doesn't end up being appended to some other namespace when the module ispackage MyModule;
line and rely on theclass MyModule
instead, as it seemsuse
d. Thanks for clarifying!- There's no
BUILDARGS
, but you can overridenew()
: this seems to run contrary to Moose::Manual::BestPractices, but then again, p5-mop isn't Moo*. - Attributes are private to a class; overriding default values for attributes in subclasses, a la
has '+foo'
doesn't work as you might expect. As Stevan and others said on IRC, prefer to have attributes with thebuilder
trait, or if your attribute is a non-reference/simple scalar, just overridenew
in your subclass, calling$class->next::method
with the new defaults. meta
when you need it; the "m" in "mop" is something I haven't really had much time using (especially since I worked with Moo first, which did not have any metaprogramming facilities at all,) so I feel I want to read up more on other modules that make use of it extensively.- Twigils! This is just freshly added to p5-mop-redux from Perl 6 (just as p5-mop-redux itself is looking to be like Perl 6 classes.) The initial implementation doesn't seem to support @!array or similar yet, just sticking to simple $!scalar variables, but it looks promising.
- It is all a work in progress; both my own module and p5-mop are still early in their implementation, which is probably a contributing factor for my ease of doing the port. Furthermore, porting showed me some things along the way that I may probably change in my module later, like handling subclassing issues and the like.
In the end, I actually got a fewer lines of code (as the old Moo code forced me to have quick lexical copies of accessors in order to stick to its encapsulation.) Granted, it does look less than the classical plain Perl 5 or Moo* class, but it does look like a good start for a MOP system that could be included in future Perl core.
Zak - Thanks for the blog post, getting feedback like this is critical to the success of p5-mop.
One thing to note, we currently do not have plans to support @!array or %!hash for attributes, this is because you cannot actually store an array or hash, you can only store a array-ref or hash-ref, both of which use the scalar sigil (and therefore the scalar twigil too). If we could manage to figure out the semantics of it, I would love to support it, but at the moment we are punting on it.
Nice porting experience :) It should motivate others to do so
No worries about the support for @!array or %!hash, I gather it is the same in Moo* anyhow as we can only store refs (e.g. using
sub { [] }
in default trait for an attribute referring to an array.