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