Re: chained accessors
[email protected] ("Carl Franks")
| Newsgroups | perl.moose |
|---|---|
| Message-ID | <[email protected]> |
On 21/11/06, Stevan Little <[email protected]> wrote: > Carl, > > On Nov 21, 2006, at 4:27 AM, Carl Franks wrote: > > Can anyone give me any pointers to how I might create "chained" > > accessors which return $self when called as a setter. > > If I do: > > has( foo => ( is => 'rw' ) ); > > I've found using the debugger, that $x->foo('y') calls > > Moose::Meta::Method::Accessor::generate_accessor_method() > > But I can't figure out how to wrap that (and whether that's the > > right approach). > > Wrapping is not the right approach, subclassing is. This is pretty > much what you will need to do (this code is untested though). > > package Foo::Chained::Attribute; > use Moose; > > extends 'Moose::Meta::Attribute'; > > sub accessor_metaclass { 'Foo::Meta::Method::Accessor::Chained' } > > package Foo::Meta::Method::Accessor::Chained; > use Moose; > > extends 'Moose::Meta::Method::Accessor'; > > sub generate_writer_method { > my $self = shift; > my $attr = $self->associated_attribute; > return sub { > my ($instance, $value) = @_; > $attr->set_value($instance, $value); > $instance; > } > } > > sub generate_accessor_method { > my $self = shift; > my $attr = $self->associated_attribute; > return sub { > my $instance = shift; > if (@_) { > $attr->set_value($instance, $value); > $instance; > } > $attr->get_value($instance, $value); > } > } > > Then at this point, you should be able to do this: > > > package Foo; > > use Moose; > > has 'foo' => (is => 'rw', 'metaclass' => 'Foo::Chained::Attribute'); > > The only issue here is going to be performance. The set_value and > get_value methods on the attribute metaclass are not very fast (they > do too much runtime calculation), and normally we inline and eval the > accessor methods. However the inlining code is not currently suited > to wrapping/altering in this way. If you are so inclined, I would be > happy to give you a commit-bit and you can refactor the inlining code > to your needs. I've noticed from Devel::Cover results, that only generate_accessor_method() is being called. Do you know, under what circumstances would generate_writer_method() be called? Carl