使用下面的例程定义
sub bar( Int @stuff ) {
return [+] @stuff;
}
以下两行都失败了:
say bar( ^3 );
say bar( [1,2,3] );
有错误
Type check failed in binding to parameter '@stuff';
expected Positional[Int] but got Array ($[1, 2, 3])
但是,赋值给具有相同定义的变量是有效的
my Int @works = [1,2,3] ;
say bar( @works );
显然,变量赋值和参数绑定不能以完全相同的方式工作,但是因为类型检查是严格的吗? 或者还有其他机制吗?
分配是一种复制操作。当我们说:
my @a = @b;
然后呢:
@b
的迭代器@a
的插槽中这就是为什么未来分配到@b
(或push
es,或pop
s等)不会影响@a
。 (顺便说一句,这也意味着my @a = [1,2,3]
相当浪费,因为它构造了一个匿名的Array
,只是迭代它然后立即将它留给GC。)
当我们有:
my @a = 1, 2, 3;
my Int @b = @a;
然后对每个赋值执行类型检查到@b
的一个槽。这是重要的价值观。当然,我们必须进行O(n)类型检查,但=
的语义意味着我们正在进行O(n)操作。
相反,绑定是一种混叠操作。它使符号引用成为一个值。这是O(1)操作。如果我们有:
my @a = 1, 2, 3;
my Int @b := @a;
然后它必须失败,因为@a
没有适当的约束。我们不能只通过@a
并检查它的值是Int
;例如,它改变了操作的复杂性,使代码的性能难以推理,但是,@a
后来可能会将1.5
分配给它,使@b
的类型约束变得毫无意义,因为它别名同样的东西。
参数传递通过绑定工作,从而在问题中观察到效果。