On Mon, Oct 12, 2009 at 5:54 AM, Ovid <publiustemp-catal...@yahoo.com> wrote: > ----- Original Message ---- > >> From: Jesse Luehrs <d...@tozt.net> > >> > package Thing; >> > use Moose; >> > with ( >> > DoesRobot => { excludes => 'draw', aliases => { draw => >> > 'draw_with_arm' }, >> > 'DoesDrawable' >> > ); >> >> Again, if the robot was a delegate rather than a role, you'd have >> $thing->draw_with_arm delegated to $thing->robot_arm->draw, but >> $thing->robot_arm->draw would still be available to be called >> separately: >> >> package Thing; >> use Moose; >> with 'DoesDrawable'; >> >> has robot_arm => ( >> is => 'ro', >> isa => 'RobotArm', >> default => { RobotArm->new }, >> handles => { draw_with_arm => 'draw' }, >> ); > > I've been trying to write up a response to this and I note that the > delegation example isn't equivalent. Consider the following code: > > #!/usr/bin/perl > > { > package RobotArm; > use Moose; > use Data::Dumper; > sub draw { print STDERR Dumper( \...@_ ); } > } > { > package Thing; > use Moose; > has robot_arm => ( > is => 'ro', > isa => 'RobotArm', > default => sub { RobotArm->new }, > handles => { draw_with_arm => 'draw' }, > ); > } > my $thing = Thing->new; > $thing->draw_with_arm; > > That will print out: > > $VAR1 = [ > bless( {}, 'RobotArm' ) > ]; > > In short, the robot arm doesn't know what to draw because the original > invocant is not passed. How is this handled in Moose? I assume it's a > matter of somehow passing the invocant to the default?
Actually in your original email you never specified that was part of the problem domain (you did however allude to it). The obvious solution is: sub draw_self_with_arm { my $self = shift; $self->draw_with_arm($self); } or to not set up the delegate method at all and simply do sub draw_with_arm { my $self = shift; $self->robot_arm->draw($self); } Which is I *think* equivalent to what you were going to implement when you said: >>> What's the easiest way to *not* worry about this method being renamed? Is >>> it something like this awful pseudo-code? >>> >>> $thing->meta->does_role('DoesRobot')->get_method('draw')->($thing); >>> >>>Does that make sense? A direct translation of this would be (using the delegation Jesse showed) $thing->draw_with_arm($thing) or alternatively $thing->robot_arm->draw($thing) -Chris UPDATE: Jesse just replied with an example of passing the current instance into the RobotArm class, I intentionally chose to ignore that because it wasn't in your original examples and it seems a poor way to create a RobotArm class, but in other cases it would be easiest and probably the best solution.