The output of your code on my computer is:

Useless use of reference constructor in void context at /home/ezhouxu/test/
t.pl line 11.
not ok 1 - So far so good
#   Failed test 'So far so good'
#   at /home/ezhouxu/test/t.pl line 19.
#          got: '2'
#     expected: '4'
not ok 2 - Not so good - returns 12
#   Failed test 'Not so good - returns 12'
#   at /home/ezhouxu/test/t.pl line 21.
#          got: '3'
#     expected: '6'
not ok 3 - Really not so good, now returns 8!
#   Failed test 'Really not so good, now returns 8!'
#   at /home/ezhouxu/test/t.pl line 22.
#          got: '2'
#     expected: '4'
1..3
# Looks like you failed 3 tests of 3.

Shell returns 3

but I think I got your point. So basically even if I run
meta->make_immutable on an constructed object, it is applied to the whole
__CLASS__, not just the object.

What I want to do is to 'with' different Roles depending on the user
arguments passed to 'new' constructor, and then make the object immutable.
is that possible?




2011/12/1 Tomas Doran <bobtf...@bobtfish.net>

>
> On 1 Dec 2011, at 08:42, woosley. xu. wrote:
>
>  Hi all,
>>   Is this a Moose make_immutable bug?
>>
>
> No.
>
>
>  package b;
>> use Moose;
>> around 'BUILDARGS' => sub {
>>   my $orig = shift;
>>   my $self = shift;
>>
>
> This happens at object construction time! Meaning you will apply the 'a'
> role once for every object you ever construct. (Meaning method modifiers
> will apply N times, where N is number of objects you've constructed).
>
>
>    with 'a';
>>   $self->$orig;
>> };
>> sub BUILD {
>>   my $self  = shift;
>>   $self->meta->make_immutable;
>> }
>>
>
>
> So what happens is that the first object creation adds the role to the
> _class_, and then makes the _class_ immutable.
>
> The second object you construct then tries to add the role to the class
> (again), and this fails - as the class is immutable.
>
> You really really don't want to be having class-wide effects whenever you
> construct an instance of the class, and make immutable telling you that
> you're doing something insane is absolutely correct here.
>
> Consider:
>
> package Double;
> use Moose::Role;
>
> around foo => sub { my ($orig, $self, @args) = @_; $self->$orig(@args) * 2
> };
>
> package Class;
> use Moose;
>
> sub { with 'Double'; };
>
> has foo => (
>    is => 'ro'
> );
>
> package main;
>
> use Test::More;
>
> my $four = Class->new(foo => 2);
> is $four->foo, 4, 'So far so good';
> my $six = Class->new(foo =>  3);
> is $six->foo, 6, 'Not so good - returns 12';
> is $four->foo, 4, 'Really not so good, now returns 8!';
>
> done_testing;
>
> The last case being the key one - just by constructing a 2nd instance,
> you've had effects on what should be a totally un-related first instance -
> epic fail!
>
> Cheers
> t0m
>
>


-- 
woosley.xu.    http://twitter.com/redicaps

Reply via email to