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