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

问题描述 投票:7回答:1

使用下面的例程定义

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

显然,变量赋值和参数绑定不能以完全相同的方式工作,但是因为类型检查是严格的吗? 或者还有其他机制吗?

perl6
1个回答
11
投票

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

my @a = @b;

然后呢:

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

这就是为什么未来分配到@b(或pushes,或pops等)不会影响@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的类型约束变得毫无意义,因为它别名同样的东西。

参数传递通过绑定工作,从而在问题中观察到效果。

© www.soinside.com 2019 - 2024. All rights reserved.