绑定到例程参数的严格类型检查

时间:2019-03-28 19:56:53

标签: perl6

下面的例程定义

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 );

显然变量分配和参数绑定不能以完全相同的方式工作,但这是因为类型检查很严格吗?
还是还有其他机制在起作用?

1 个答案:

答案 0 :(得分:11)

分配是一项复制操作。当我们说:

my @a = @b;

然后:

  1. @b获得迭代器
  2. 对其进行迭代,将每个值分配到@a的插槽中

这就是为什么将来分配给@b(或push,或pop等)的原因不会影响@a的原因。 (顺便说一句,这也意味着my @a = [1,2,3]是相当浪费的,因为它构造了一个匿名Array,只是对其进行迭代,然后立即将其留给GC使用。)

当我们拥有:

my @a = 1, 2, 3;
my Int @b = @a;

然后,对每个分配进入@b插槽中的类型进行检查。重要的是价值观。当然,我们必须进行O(n)类型检查,但是=的语义意味着无论如何我们都在进行O(n)操作。

相比之下,绑定是 aliasing 操作。它使符号引用成为值。它是O(1)操作。如果我们有:

my @a = 1, 2, 3;
my Int @b := @a;

然后它必须失败,因为@a没有受到适当的约束。我们不能只检查@a并检查其值为Int;一方面,它会改变操作的复杂性,使代码的性能难以为继,但@a之后可能会分配给1.5,例如@b上的类型约束毫无意义,因为它是同一件事的别名。

参数传递通过绑定进行,因此在问题中观察到的效果。