动态变量、CALLERS、标量和赋值
Dynamic variables, CALLERS, Scalars, and assignment
我最近注意到,在大多数使用赋值的情况下,重新初始化动态变量并没有我预期的语义(但是,绑定按照我预期的方式工作)。
具体来说,在这段代码中:
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 的值。关于赋值的语义,我缺少什么?
What am I missing about the semantics of assignment?
我认为您遗漏的内容与动态变量本身没有任何关系。我认为您缺少的是:
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
es,因为每次调用都是全新的。
关于 sub g
中 $*i
的值:这也只是增加调用者 $*i
的 copy,所以值每次通话都保持 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],]
我最近注意到,在大多数使用赋值的情况下,重新初始化动态变量并没有我预期的语义(但是,绑定按照我预期的方式工作)。
具体来说,在这段代码中:
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 的值。关于赋值的语义,我缺少什么?
What am I missing about the semantics of assignment?
我认为您遗漏的内容与动态变量本身没有任何关系。我认为您缺少的是:
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
es,因为每次调用都是全新的。
关于 sub g
中 $*i
的值:这也只是增加调用者 $*i
的 copy,所以值每次通话都保持 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],]