develooper Front page | perl.moose | Postings from March 2009

Trait injection - request for ad hominem attacks

Thread Next
From:
Sartak
Date:
March 24, 2009 21:08
Subject:
Trait injection - request for ad hominem attacks
Message ID:
e7e9b6ab0903242108v1455c86cn83a3dd1fe9b764de@mail.gmail.com
Hi all,

I wrote an extension, MooseX-InstanceTracking. It's on CPAN (
http://search.cpan.org/~sartak/MooseX-InstanceTracking/lib/MooseX/InstanceTracking.pm
) and github ( http://github.com/sartak/moosex-instancetracking/tree/master
). The idea of this extension is that metaclasses will cache all
instances of the class. It cleanly modifies several metaclass methods
such as construct_instance, clone_instance, rebless_instance, etc.

The issue I'm running into is make_immutable. Within the
MooseX::InstanceTracking role (to be applied to Moose::Meta::Class),
there's no way to hook into the *inlined* constructor. The inlined
constructor intentionally does not call meta methods because that's
what's slow to begin with!

I could easily define a trait for Moose::Meta::Method::Constructor
that calls track_instance on the metaclass. The problem is telling my
metaclass to use this constructor trait. Moose *does* have some
support for allowing a subclass to declare that it wants to use a
different constructor metaclass. Unfortunately, this is not enough.
Two extensions that want to provide behavior in inlined constructors
cannot compose. This sucks!

Attributes have some special magic where you can set a metaclass and
some traits. It'd be great to extend this pluggability to all
"associated metaclass" methods. Moose::Meta::Class would have a
constructor_traits method that by default returns an empty list. Roles
can modify this method to inject new traits. To be more concrete, what
I'd ultimately love to do is:

    package My::Class::Trait;
    use Moose::Role;

    around constructor_traits => sub {
        my $orig = shift;
        my @traits = $orig->(@_);

        push @traits, 'My::Constructor::Trait';

        return @traits;
    };

    package My::Constructor::Trait;
    use Moose::Role;

    around _generate_instance => sub {
        ....
    };

This way extensions that need to inject traits into associated
metaclasses would be able to compose. However, do you guys think this
would have unhappy implications for metaclass compatibility? It's one
topic I've not pondered too deeply over. (I really need to finish
reading AMOP!) Can anyone think of other potential issues?

Shawn

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About