Re: make_immutable bug?

[email protected] (Tomas Doran)
Newsgroups perl.moose
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.