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


Reply via email to