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.

Reply via email to