TL;DR我在为什么会这样?中提供了一个相对简单的答案,但是,这种解释可能不够充分1,所以我查看从范围声明和初始化类型化数组中的一些替代方法。
为什么会这样?
my @a; 声明一个新的Array(初始化为空)并将其“绑定”到符号@a。因此my @a; say @a.^name 返回Array。不需要在数组的声明或初始化中使用 Array 这个词——@ 就足够了。2
my @a = 'a'..'z' 尝试复制'a' 到'z' 范围内的每个值,一次一个,复制@a[0],@ 987654337@ 等。绑定到@a 的新数组对其每个元素都有一个类型约束(在下一节中解释);它将检查每个值(并且会成功)。
my Array @a 声明了一个Array,其元素具有Array 类型约束(因此它是一个数组数组)。 my Array @a; say @a.^name 返回 Array[Array] 以表明这一点。 my Array @a = 'a'..'z'; 在复制第一个值 ("a") 时失败,因为它是 Str 值而不是 Array。
声明并初始化一个范围内的类型化数组
my @a = 'a'..'z';
该语句的my @a 部分声明了一个变量,该变量绑定到(引用)一个Array 类型的新数组。因为没有指定元素类型约束,所以新数组的元素被约束为与 P6 中的 Most un假设类型 Mu 一致。换句话说,它是一个空数组,可以包含您想要放入的任何值。 (可以说say @a.^name 显示Array 而不是Array[Mu],因为[Mu] 被认为是Most uninteresting。)
... = 'a'..'z' 初始化新数组。初始化对数组已经建立的类型约束没有影响。它只是将字符串'a'、'b' 等的副本传递到数组中(自动扩展以将它们接收到@a[0]、@a[1] 等中)。
我建议开发人员避免对变量添加显式类型约束和显式强制值,除非他们确信它们是可取的。 (参见我在an earlier SO answer 末尾的括号注释。)也就是说,您可以选择这样做:
my Str @a = 'a'..'z'; # `Array` elements constrained to `Str`
my Str @a = (0..99)>>.Str; # Coerce value to match constraint
另外,P6 支持对值或值列表进行显式绑定,而不是赋值。最常见的方法是使用:= 而不是=:
my @a := 'a'..'z'; say @a.WHAT; say @a[25]; # (Range)z
注意@a 的显式绑定意味着@a没有绑定到新的Array,而是绑定到Range 值。因为Range 可以像Positional 一样工作,所以位置下标仍然有效。
以下语句在 imo 中是非常多余的显式类型,但它们都可以工作并产生完全相同的结果,尽管第一个语句会更快:
my Str @a := Array[Str].new('a'..'z');
my Str @a = Array[Str].new('a'..'z');
关于这个话题还有很多要讨论的,但也许前面的内容足以解决这个问题/答案。如果没有,请在您的原始问题下方和/或下方在 cmets 中提出更多问题。
脚注
1 此答案的早期版本开头为:
my Array @a ...
# My array of thoughts raised by this declaration
# and your questing "why?" in this SO question
# began with wry thoughts about complicated answers
# about reasons your array is awry and pedances
(我编造了“pedances”这个词来表示看起来很迂腐,但如果使用得当却能很好地流动——一旦你熟悉了它明显的特殊但自然就会发生这种情况实际上很有帮助的性质。更重要的是,我需要一些与“答案”押韵的东西。)
2下面是P6中@含义的几个助记词: