在Perl 6中,我可以使用数组作为哈希键吗?

时间:2018-04-26 20:04:12

标签: arrays hash hashmap key perl6

在Hash文档中,Object keys部分似乎暗示您可以使用任何类型作为哈希键,只要您指出但我在尝试使用数组作为键时遇到问题:< / p>

> my %h{Array};
{}
> %h{[1,2]} = [3,4];
Type check failed in binding to parameter 'key'; expected Array but got Int (1)
in block <unit> at <unknown file> line 1

有可能这样做吗?

2 个答案:

答案 0 :(得分:8)

[1,2]内的%h{[1,2]} = [3,4]被解释为切片。因此,它会尝试分配%h{1}%{2}。由于密钥必须是Array,因此不能很好地检查。这是错误消息告诉您的内容。

如果您逐项列出数组,它“确实”有效:

my %h{Array};
%h{ $[1,2] } = [3,4];
say %h.perl;  # (my Any %{Array} = ([1, 2]) => $[3, 4])

然而,这可能无法得到你想要的东西,因为:

say %h{ $[1,2] };  # (Any)

那是因为对象哈希使用.WHICH方法的值作为底层数组中的键。

say [1,2].WHICH; say [1,2].WHICH;
# Array|140324137953800
# Array|140324137962312

请注意,那些看似相同的数组的.WHICH值是不同的。 那是因为Array s是可变的。由于List可以,所以这不会真正发挥作用。

那你想要实现什么目标?如果数组中值的顺序不重要,您可以使用Set作为键:

say [1,2].Set.WHICH; say [1,2].Set.WHICH
# Set|AEA2F4CA275C3FE01D5709F416F895F283302FA2
# Set|AEA2F4CA275C3FE01D5709F416F895F283302FA2

请注意,这两个.WHICH是相同的。所以你可以把它写成:

my %h{Set};
dd %h{ (1,2).Set } = (3,4); # $(3, 4)
dd %h; # (my Any %{Set} = ((2,1).Set) => $(3, 4))

希望这能澄清事情。更多信息:https://docs.perl6.org/routine/WHICH

答案 1 :(得分:3)

如果您出于某种原因真的只对使用对象哈希感兴趣,请参阅Liz的答案,特别是a similar earlier question的答案和评论。

答案的(最终 1 )重点是使用Array之类的[1,'abc',[3/4,Mu,["more",5e6],9.9],"It's {<sunny rainy>.pick} today"]作为常规字符串哈希键的简单方法

基本原则是使用.perl来近似不可变"value type"数组,直到存在具有更强大值类型Positional的规范不可变.WHICH类型为止

使用数组作为哈希键的简单方法

my %hash;
%hash{ [1,2,3].perl } = 'foo';
say %hash{ [1,2,3].perl }; # displays 'foo'

.perl将其参数转换为string Perl 6代码,该代码是该参数的literal版本。

say [1,2,3].perl;    # displays '[1, 2, 3]'

请注意如何添加空格,但这并不重要。

这不是一个完美的解决方案。如果你在密钥访问之间改变数组,你显然会得到破坏的结果。不太明显,您会得到与.perl中的任何限制或错误相对应的损坏结果:

say [my %foo{Array},42].perl; # displays '[(my Any %{Array}), 42]'

1 希望这是我对你的问题的最终答案的结束。有关使用前缀~来实现更有限但类似效果的替代方法的讨论,请参阅my earlier 10th (!!) version of this answer和/或尝试在下面的评论中了解我与Liz的交流。