关于变量的Perl 6文档指出%
sigil可以与执行Associative角色的类型一起使用。它特别提到了Pair,Hash和Map。但是,如何使用%
如果我使用类型约束,我会收到一个奇怪的错误:
> my Pair %pair = Pair.new( 'a', 'b' )
Type check failed in assignment to %pair; expected Pair but got Str ("b")
in block <unit> at <unknown file> line 1
如果我在没有类型约束的情况下分配,我会得到一个哈希:
my %pair = Pair.new: 'a', 'b'; # Hash, not Pair
绑定工作:
my %pair := Pair.new: 'a', 'b'; # Pair
但是如果我使用类型约束,我会得到另一个奇怪的错误:
> my Pair %p2 := Pair.new: 'a', 'b';
Type check failed in binding; expected Associative[Pair] but got Pair (:a("b"))
in block <unit> at <unknown file> line 1
同样的问题出现在Set和Map上。使用Hash执行该操作,最终得到一个可变的pen。
我认为这里有各种各样的问题,但也许%
sigil并不像我所认为的那样多才多艺。
答案 0 :(得分:9)
如果我们想了解您的示例中发生了什么,我们需要退一步:
变量绑定到对象。默认情况下,sigilled变量最初绑定到可分配的容器对象(Scalar
和$
为&
,Array
为@
,Hash
为%
{1}})。
如果将类型添加到变量声明中,例如
my Int %var
或等效
my %var of Int
您对此容器可能包含的值的类型设置了限制。
变量赋值(=
)尝试将右侧的值放入绑定到左侧变量的容器中,如果不满足此类型约束,则会失败。默认情况下,只有&
个变量带有这样的约束(参见(my &).VAR.of
vs (my %).VAR.of
)。
相反,重新绑定变量(:=
)将替换容器对象。如果您想限制哪些类型的对象可以绑定,则需要is
而不是of
:
my %var is Pair;
%var := x => 1; # ok
%var := 42; # not ok
Sigilled变量意味着默认类型约束($
无效,Callable
为&
,Positional
为@
,Associative
为%
1}})。请注意,此默认约束会被显式约束覆盖,例如
my %var is Int;
%var := 42; # ok even though 42 is not Associative
最后,请注意is
不仅仅设置类型约束,还会将变量绑定到新创建的该类型的实例:
my %pair is Pair;
say %pair; # (Mu) => (Mu), ie Pair.new()
我不知道如何做前者。
答案 1 :(得分:3)
您可以使用%
sigiled容器来保存does
Associative
角色的任何值。
正如您所发现的那样,您必须小心宣告和分配。
在您的示例my Pair %pair
中,您要说的是Hash
(不是Pair
)可以保留Pair
个值(%pair.WHAT = 'Hash[Pair]'
)< / p>
试试这个:
my Pair %p2 = mykey => Pair.new: 'a', 'b';
这可能很好。通过约束值的类型,如果你说
,你会收到错误%p2<c> = 'd';
因为您没有分配Pair
。
正如您所发现的那样,绑定的工作方式与您认为应该的方式相同。
答案 2 :(得分:1)
老实说,这对我来说就像一个小虫。 %
容器存储通过胖箭头中缀构造函数构造的Pair
没有问题:
my %pair = what => 'a pair';
容器会覆盖该类型,因此您获得Hash
而不是Pair
。
%pair.WHAT; #=> (Hash)