动态变量、CALLERS、标量和赋值



我最近注意到,在大多数使用赋值的情况下,重新初始化动态变量并没有我期望的语义(然而,绑定的工作方式与我期望的一样(。

具体来说,在此代码中:

sub g {
my $*i  = CALLERS::<$*i>  // 0;
my $*a1 = CALLERS::<$*a1> // Array.new;
my @*a2 = CALLERS::<@*a2> // Array.new;
$*i++;
$*a1.push: 'v1';
@*a2.push: 'v2';
dd $*i;
dd $*a1;
dd @*a2;
}
sub f {
my $*i = 0;
my $*a1 = Array.new;
my @*a2 = Array.new;
g; g; g;
}
f

我期望3["v1", "v1", "v1"]["v2", "v2", "v2"]的输出,但却得到了1$["v1", "v1", "v1"]["v2"]。切换到绑定解决了这个问题,所以我不想解决任何问题——但我很想理解为什么分配在这里不起作用。我注意到,指向数组的标量可以工作,但指向Int的标量则不行。但在任何一种情况下,我都会认为新分配的变量将从CALLERS接收值。关于赋值的语义,我缺少什么?

在赋值的语义方面我缺少什么?

我认为你所缺少的与动态变量本身无关。我认为你缺少的是:

my @a = Array.new;

基本上是一个角落。由于单参数规则,它与相同

my @a = ();

与相同

my @a;

因此,在sub f中的示例中

my @*a2 = Array.new;

in只是在动态变量中设置一个空数组。

然后在sub g中:

my @*a2 = CALLERS::<@*a2> // Array.new;

基本上只是在做(因为单参数规则(:

my @*a2;

因此,你看不到以前做过的push,因为每次通话都是新鲜的。

关于sub g$*i的值:这也只是增加调用方$*i副本,因此在每次调用中该值都保持在1

$*a1之所以有效,是因为容器化停止了单参数规则的扁平化行为。观察以下两者之间的差异:

sub a(+@a) { dd @a }; a [2,3,4];  # [2,3,4]

和:

sub a(+@a) { dd @a }; a $[2,3,4];  # [[2,3,4],]

相关内容

  • 没有找到相关文章

最新更新