I just completed a section on code generation in the Modern Perl book draft. Per an interesting coincidence, Moose and Class::MOP reached 1.0 on the same day.
What's the coincidence? The final subsection of Code Generation discusses the use of Class::MOP for metaprogramming.
It's simple to explain code generation and metaprogramming in terms of
string eval
; everyone who knows how to declare a class in Perl can
figure out string quoting issues and the particular timing of BEGIN
blocks and visibility and implicit closures when writing:
eval <<END_CLASS;
package $class;
use parent '$parent';
sub new { ... }
sub get_name { ... }
sub set_name { ... }
END_CLASS;
... versus:
package My::Awesome::Subclass;
use parent 'My::Awesome::Parent';
sub new { ... }
sub get_name { ... }
sub set_name { ... }
... but you end up having to deal with all of those issues, plus the
drawbacks of string eval
(it's slower than regular declaration,
you don't get syntax highlighting or other IDE tools, it may leak memory in
some versions of Perl 5, quoting can be a pain, parameterization is an exercise
in templating systems rather than OO design, and there's no introspection or
mechanism to modify the code after you've run it through
eval
).
You also don't get guarantees that you've written your code correctly; you
might have left out an important method or an important declaration, or you may
manipulate @ISA
in a messy or unfortunate way, or you may step all
over an existing class elsewhere, or....
It's important to have the safety valve of string eval
, at
least so that experienced programmers can escape from the cozy confines of what
the language itself has provided if they're doing brilliant things or if
they're doing dirty things and have made the sufficient determination that the
risk of getting caught for cheating is worth the value of getting things done
quickly.
Yet Class::MOP
for all of its perceived metacircular
brain-twisting confusion (and there's really only one secret to learn to
untwist all of that perceived complexity, unless you want to implement or
bootstrap the system) gives you all of that power and more, and all of the
missing correctness, and all of the syntax highlighting, and all of the "Hey,
this is just Perl I don't have to quote or worry about timing or anything
wild!" if you learn that one little secret: you're only manipulating
objects.
Yes, the perceived syntactic weight of creating a class with
Class::MOP
is higher than eval "package Foo; \@ISA =
'Bar';";
, but you get introspection. You get interoperability. You get
the benefit of a suite of thousands of tests and hundreds of real-world modules
on the public CPAN alone ensuring that the system works. Just as Moose
makes the right designs easy to choose, so too does using a formalized
mechanism for metaprogramming make metaprogramming safer and easier.
(As well, anything which hides some of the gory details of Perl 5 implementation behind a nicer syntax than what Perl 5 provides in this area is an improvement on those terms alone.)
So, are you going to tell us what the secret is? :-)
@pozorvlak, the secret is "You're manipulating objects."
Those objects represent entities in your system in the same way that the ASTs you manipulate in a homoiconic language such as Lisp or the objects you manipulate in a Smalltalk image represent entities in the program.
Maybe this is the profound enlightenment that Lisp or Smalltalk programmers get, then take for granted.