Perl 6可以将%sigil用于哈希以外的其他东西吗?

时间:2017-05-19 01:43:22

标签: associative perl6

关于变量的Perl 6文档指出% sigil可以与执行Associative角色的类型一起使用。它特别提到了PairHashMap。但是,如何使用%

将变量Pair变为Bag

如果我使用类型约束,我会收到一个奇怪的错误:

> 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

同样的问题出现在SetMap上。使用Hash执行该操作,最终得到一个可变的pen

我认为这里有各种各样的问题,但也许% sigil并不像我所认为的那样多才多艺。

3 个答案:

答案 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)