total 方法和 Perl 6 中 Bag 变量的标志

total method and the sigil of a Bag variable in Perl 6

我们可以使用total方法来知道Bag中所有权重的总和。

> my $b = (1,2,1).Bag
Bag(1(2), 2)
> $b.total
3

但是如果我们使用 % 印记而不是 $ 作为我们的 Bag,我们会收到一条错误消息。

> my %b = (1,2,1).Bag
{1 => 2, 2 => 1}
> %b.total
No such method 'total' for invocant of type 'Hash'. Did you mean 'cotan'?
  in block <unit> at <unknown file> line 1

如果在 total 之前将 %b 显式转换为 Bag,则有效:

> %b.Bag.total
3

问题:我以前以为用SetBagSetHash等,用% 印记是可取的。我错了吗?

绑定而不是分配

my %b := (1,2,1).Bag;
say %b.total

绑定(与 :=binds the right hand side directly to the left hand side. In this case a value that does the Associative 角色被绑定 %b.

或分配给Bag

分配(使用=assigns(复制)值来自右侧进入左侧的容器

您可以在第一次绑定到 Bag 后分配,如下所示。

紧接在赋值之前,my 声明符会将合适的容器绑定到声明的变量。默认情况下,如果变量具有 % 标记,它将是一个 Hash 容器。

但是您可以指定一个变量 is 绑定到与其印记兼容的其他类型的容器:

my %b is Bag = 1,2,1;
say %b.total

对于这个咒语,你需要使用 = 因为,当遇到运算符时 %b 已经绑定到 Bag 现在你需要分配(复制) 变成 Bag.

这样你就可以简单地提供一个值列表(没有显式键或 Bag coercer/constructor 必要)因为 = 是根据容器的需要解释的在它的左边,Bag 选择将 = 的 RHS 解释为一个键列表,其出现次数对它很重要。

在 Perl 6 中,assignment to a container can be coercive,也就是说,它将值强制转换为容器的值。看到这个:

my $b = (1,2,1).Bag;
say $b.^name; # Bag

my %haШ = (1,2,1).Bag;
say  %haШ.^name; # Hash

绑定,另一方面,binds the type of the container to the contained thing

因此,答案:您仍然可以使用印记,但正如@raiph 上面所说,使用绑定,这样 Bag 或 BagHash 就不会被强制转换为简单的哈希。

my %real-haШ := (1,2,1).Bag;
say %real-haШ.^name; # Bag