Perl 为什么要声明在Moose中返回子例程引用的子例程?

Perl 为什么要声明在Moose中返回子例程引用的子例程?,perl,moose,Perl,Moose,我是perl中的Moose新手,当我遇到这个我不太理解的文档时,我一直在阅读它的文档: 如果要使用任何类型的引用作为默认值,必须从子例程返回它好的,我得到了这个陈述,下一个例子 has 'mapping' => ( is => 'ro', default => sub { {} }, ); 这是必要的,因为否则Perl将实例化引用一次,并且它将被所有对象共享:我不理解这一点,它将实例化引用一次并被所有对象共享是什么意思?怎么做? has

我是perl中的Moose新手,当我遇到这个我不太理解的文档时,我一直在阅读它的文档:

如果要使用任何类型的引用作为默认值,必须从子例程返回它好的,我得到了这个陈述,下一个例子

has 'mapping' => (
      is      => 'ro',
      default => sub { {} },
  );
这是必要的,因为否则Perl将实例化引用一次,并且它将被所有对象共享:我不理解这一点,它将实例化引用一次并被所有对象共享是什么意思?怎么做?

 has 'mapping' => (
      is      => 'ro',
      default => {}, # wrong!
  );
如果将裸非子例程引用作为默认值传递,Moose将抛出错误


如果Moose允许这样做,那么默认映射属性很容易在多个对象之间共享。相反,将其包装在一个子例程引用中,正如我们上面看到的不要再这样做了

,因为它会在远处产生动作,这是不好的。问题说明:

package Wrong;
my $default = {};

sub new {
    my ($class) = @_;
    return bless $default => $class;
}

package main;
use 5.010;
my @wobj;
push @wobj, Wrong->new for 0..2;

$wobj[0]->{some_new_attr} = 'foobar';

use Data::Dumper qw(Dumper);
print Dumper $wobj[1];  # huh????!
print Dumper $wobj[2];  # that one, too?! why?

say for @wobj;          # ah, it's the same shared address

package Correct;
my $default = sub { return {} };

sub new {
    my ($class) = @_;
    return bless $default->() => $class;
}

package main;
my @cobj;
push @cobj, Correct->new for 0..2;

$cobj[0]->{some_new_attr} = 'foobar';

print Dumper $cobj[$_] for 0..2; # instances 1 and 2 are unaffected

say for @cobj;          # all different addresses

{}
不是一个子程序引用,它是一个哈希引用。对不起,不是。在你详细引用的官方文档和我的答案之间,没有留下任何东西。我的答案解释了一个实验,你可以运行并逐步通过调试器检查它的输出。现在由你来精确地指出你不能理解的部分,并传达这一点。