声明并初始化范围内的类型化数组

Jes*_*wak 14 arrays typing range perl6 raku

我最近尝试my Array @a = 'a'..'z';my Array @a = @('a'..'z');

两者都会产生以下错误:

Type check failed in assignment to @a; expected Array but got Str ("a")
in block <unit> at <unknown file> line 1
Run Code Online (Sandbox Code Playgroud)

但是,在没有类型的情况下进行初始化会起作用,并且似乎最终会产生一个Array:

> my @a = 'a'..'z';
> @a.^name
Array
Run Code Online (Sandbox Code Playgroud)

为什么会这样呢?

rai*_*iph 12

TL; DR这种情况下,我提供了一个相对简单的答案但是,该解释可能不足1,因此我回顾了Declare中的一些替代方法并从范围中初始化类型化数组。

为什么会这样呢?

  • my @a;声明一个新的Array(初始化为空)并将其“绑定”到符号@a。从而my @a; say @a.^name回报Array。无需Array在数组的声明或初始化中使用该词- @足够了。2

  • my @a = 'a'..'z'试图拷贝每一个值的范围内'a''z'一个,在一个时间, @a[0]@a[1]等绑定到新的数组@a具有类型约束为它的每个元素(在下一节解释); 将检查每个值(并将成功)。

  • my Array @a声明一个对其类型Array具有Array类型约束的元素(因此它是一个数组数组)。my Array @a; say @a.^name返回Array[Array]以表明这一点。my Array @a = 'a'..'z';复制第一个值(“ a”)时失败,因为它不是一个StrArray

声明并初始化范围内的类型化数组

my @a = 'a'..'z';
Run Code Online (Sandbox Code Playgroud)

my @a语句的一部分声明了一个变量,该变量绑定到(指)一个新的type数组Array。因为没有指定的元素类型约束,新数组元素被约束为一致Mu时,中号 OST ü在P6 nassuming类型。换句话说,它是一个空数组,准备包含要放入其中的任何值。(可以说,say @a.^name显示器Array,而不是Array[Mu]因为[Mu]被认为是中号 OST ü ninteresting。)

... = 'a'..'z'初始化新数组。初始化对数组已经建立的类型约束没有影响。它只是提供字符串的副本'a''b'了数组(自动展开迎接进入@a[0]@a[1]等等)。

我建议开发人员避免对变量和显式强制值添加显式类型约束,除非他们确信它们是理想的。(请参见我在较早的SO答案结尾处的括号内的注释。)也就是说,您可以选择这样做:

my Str @a = 'a'..'z';      # `Array` elements constrained to `Str`
my Str @a = (0..99)>>.Str; # Coerce value to match constraint
Run Code Online (Sandbox Code Playgroud)

另外,P6支持显式绑定值或值列表,而不是赋值。最常见的方法是使用:=而不是=

my @a := 'a'..'z'; say @a.WHAT; say @a[25]; # (Range)?z
Run Code Online (Sandbox Code Playgroud)

注意如何明确的结合@a方式@a一直没有被绑定到一个新的Array,而是到Range价值。并且因为a Range可以表现为a Positional,所以位置下标仍然有效。

以下语句将成为完全多余的显式键入,但它们的工作原理和结果彼此完全相同,尽管第一个语句会更快:

my Str @a := Array[Str].new('a'..'z'); 
my Str @a  = Array[Str].new('a'..'z'); 
Run Code Online (Sandbox Code Playgroud)

关于此主题还有更多的要讨论的内容,但也许前面的内容已足以解决该问题/答案。如果不是,请在原始问题和/或下面的评论中提出其他问题。

脚注

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
Run Code Online (Sandbox Code Playgroud)

(我将“ pedances”一词组成的意思是看似学究的东西,但在正确使用时会很好地流动-一旦您熟悉其明显特质但实际上很有帮助的性质,就会自然发生。更重要的是,我需要一些东西与“答案”押韵。)

2以下是一些@P6中含义的助记符:

  • 看起来像是一个零数字(0),其中带有Math Italic Small A)–并且@foo变量默认为0索引(或@)。

  • 听起来像单词“在”。数组索引具有元素。


Val*_*kas 7

设置数组中元素的类型:

my Str @a = 'a'..'z'; 
say @a; #[a b c d e f g
Run Code Online (Sandbox Code Playgroud)

要查看它是什么类型,可以使用.WHAT

my Str @a = 'a'..'z'; 
say @a.WHAT #(Array[Str])
Run Code Online (Sandbox Code Playgroud)

要测试它是否为数组,可以进行智能匹配

my Str @a = 'a'..'z'; 
say 'is array' if @a ~~ Array; #is array

say 'is str array' if @a ~~ Array[Str]; #is str array

say 'is str array' if @a ~~ Array[Int]; #
Run Code Online (Sandbox Code Playgroud)


drc*_*law 7

@('a'..'z')将一个List不是Array。将其更改为 ['a'..'z']将给出一个Array

但这仍然会在您将其分配给您时给您一个类型错误my Array @a

如果要将整个数组分配给另一个数组的元素,则必须以某种方式逐项列出,例如:

$[1,2,3]; #Still an array but treated as single item
[1,2,3], ; #Note the list operator (comma), this give you a list of lists

Run Code Online (Sandbox Code Playgroud)

因此,在您的情况下:

'a'..'z'; 是一个范围,需要转换为数组,所以

['a'..'z']; 现在将范围评估为数组

$['a'..'z']; 现在将范围评估为数组并作为单个项目

my Array @a=$['a'..'z'];

say @a;

#OUTPUT:
#[[a b c d e f g h i j k l m n o p q r s t u v w x y z]]
# Which is an array of arrays;
Run Code Online (Sandbox Code Playgroud)

不知道这是您要追求的,但是它消除了类型错误。