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

Can Perl 6 use the % sigil for something other than a Hash?

有关变量的 Perl 6 文档指出,% 印记可用于将 Associative role. It specifically mentions Pair, Hash, and Map. But, how would I get a Pair 转换为具有 %?

的变量的类型

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

> 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

同样的问题出现在 Bag and Set. Do it with Map and you end up with a mutable Hash

我认为这里存在各种问题,但也许 % 印记并不像我所相信的那样多才多艺。

您可以使用 % 标记容器来保存 does Associative 角色的任何值。

正如您发现的那样,您必须小心声明和分配的方式。

在您的示例 my Pair %pair 中,您是说制作一个 Hash(不是 Pair),它可以容纳 Pair 个值(%pair.WHAT = 'Hash[Pair]' )

试试这个:

my Pair %p2 = mykey => Pair.new: 'a', 'b';

这很好。通过限制值的类型,如果你说

,你会得到一个错误
%p2<c> = 'd';

因为您没有分配 Pair

正如您还发现的那样,绑定按照您认为的方式工作。

如果我们想了解您的示例发生了什么,我们需要退后几步:

变量绑定到对象。默认情况下,带符号的变量最初绑定到可分配的容器对象(Scalar 用于 $&Array 用于 @Hash 用于 %).

如果将类型添加到变量声明中,例如

my Int %var

或等效的

my %var of Int

您对该容器可以容纳的值的类型进行了限制。

变量赋值 (=) 尝试将右侧的值放入绑定到左侧变量的容器中,如果不满足此类型约束,则会失败。默认情况下,只有 & 个变量带有这样的约束(参见 (my &).VAR.of(my %).VAR.of)。

相比之下,重新绑定变量 (:=) 将替换容器对象。如果要限制可以绑定的对象类型,则需要 is if of:

my %var is Pair;
%var := x => 1; # ok
%var := 42;     # not ok

Sigilled 变量意味着默认类型约束(none 代表 $Callable 代表 &Positional 代表 @Associative 对于 %)。请注意,此默认约束会被显式约束覆盖,例如

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

我不知道有什么方法可以只做前者。

老实说,这对我来说就像是一个错误。 % 容器存储通过粗箭头中缀构造函数构造的 Pair 没有问题:

my %pair = what => 'a pair';

尽管容器会覆盖类型,因此您得到的是 Hash 而不是 Pair

%pair.WHAT; #=> (Hash)