Based on the "default accessors and encapsulation" thread, it seems like a
Perl 6 equivalent of Class::MethodMaker will be still be useful in our (or
at least "my") Brave New World.  I've been pondering the best way to create
such a beast in Perl 6.

The most common two Perl 5 techniques are:

1. Use a string eval: build up a big string that looks the code for the
method that I would have typed myself if I wasn't so lazy, then eval the
string and assign the resulting code ref to the appropriate typeglob.
Example:

    $attr = 'baz';
    *{"Foo::$attr"} = eval qq(sub { \$_[0]->{'$attr'} });

This technique seems to have the best runtime performance in Perl 5 (by a
small margin), but it's also much more expensive (not to mention tedious and
persnickety) to create the method in the first place.  For whatever reason,
it's always just struck me as "wrong" (sort of like source filtering where
code is just seen as a giant string--something that Perl 6 blessedly saves
us from :)

2. Use a closure: build a method by assigning what would normally be
constant values to a set of variables, then capturing their state in a
closure.  Example:

    $attr = 'baz';
    *{"Foo::$attr"} = sub { $_[0]->{$attr} };

Making the method this way has always seemed "cleaner" to me, but it bothers
me that $attr a full blown variable that has to be read from every time the
method is run.  Really, it should be a constant, which is probably why the
string eval version has a speed edge at runtime.

Obviously, simple "get" methods like the above wouldn't have to be written
at all in Perl 6.  Instead, I'd just use a public, read-only attribute ("has
$.baz") and be done with it.  (As far as I can tell, the user of my class
wouldn't be able to determine (or care) how $o.baz is implemented--whether
as "method baz() { ... } or as "has $.baz".  Correct me if I'm wrong :)

"Set" methods, OTOH, will still have to be either written manually or
auto-generated if, like me, you are not inclined to accept the "contract"
implied by "has $.foo is rw" Perl 6 attributes.

But beyond simple get/set methods, there's a whole world of increasingly
more complex kinds of generic methods to be made.  Just look at Perl 5's
Class::MakeMethods::* for some examples.  So finally, getting back to my
original point, I'm wondering how best to create a good MethodMaker in Perl
6.

The two Perl 5 techniques still seem like they will work (albeit with
different syntax), but I'm sure there are better ways...perhaps something
involving macros?  The ideal solution has the strengths of both Perl 5
techniques, but none of their weaknesses.  Creation should be fast and
clean, and there should be no wasted overhead when calling the generated
methods.  It should be just as if I wrote the methods myself.

I haven't retained enough Perl 6 syntax to have any idea what this would
look like, so I'm looking for suggestions.  Which Perl 6 features are best
suited to creating a good Perl 6 MethodMaker?  Anyone want to post some
simple examples?

-John

Reply via email to