在 Perl 6 中,我可以使用数组作为哈希键吗?
In Perl 6, can I use an Array as a Hash key?
在散列文档中,Object keys
部分似乎暗示您可以使用任何类型作为散列键,只要您指出即可,但我在尝试使用数组作为键时遇到了问题:
> 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
这可以吗?
%h{[1,2]} = [3,4]
中的 [1,2]
被解释为一个切片。所以它尝试分配 %h{1}
和 %{2}
。并且由于密钥必须是 Array
,因此不能很好地进行类型检查。这就是错误消息告诉您的内容。
如果逐项列出数组,它 "does" 有效:
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
s 可以,所以这不会真正起作用。
那么你想达到什么目的?如果数组中值的顺序不重要,您可以使用 Set
s 作为键:
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.raku.org/routine/WHICH
如果出于某种原因您真的只对使用对象哈希感兴趣,请参阅 Liz 的回答,尤其是 .
的回答和评论
这个答案的(最终1)焦点是使用Array
如[=14]的简单方法=] 作为常规字符串哈希键。
基本原理是使用.perl
来近似不可变的"value type" array until such time as there is a canonical immutable Positional
type with a more robust value type .WHICH
。
使用数组作为散列键的简单方法
my %hash;
%hash{ [1,2,3].perl } = 'foo';
say %hash{ [1,2,3].perl }; # displays 'foo'
.perl
将其参数转换为该参数的 string of Perl 6 code that's a 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 讨论使用前缀 ~
实现更有限但类似的效果的替代方法 and/or 尝试在下面的评论中了解我与 Liz 的交流。
在散列文档中,Object keys
部分似乎暗示您可以使用任何类型作为散列键,只要您指出即可,但我在尝试使用数组作为键时遇到了问题:
> 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
这可以吗?
%h{[1,2]} = [3,4]
中的 [1,2]
被解释为一个切片。所以它尝试分配 %h{1}
和 %{2}
。并且由于密钥必须是 Array
,因此不能很好地进行类型检查。这就是错误消息告诉您的内容。
如果逐项列出数组,它 "does" 有效:
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
s 可以,所以这不会真正起作用。
那么你想达到什么目的?如果数组中值的顺序不重要,您可以使用 Set
s 作为键:
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.raku.org/routine/WHICH
如果出于某种原因您真的只对使用对象哈希感兴趣,请参阅 Liz 的回答,尤其是
这个答案的(最终1)焦点是使用Array
如[=14]的简单方法=] 作为常规字符串哈希键。
基本原理是使用.perl
来近似不可变的"value type" array until such time as there is a canonical immutable Positional
type with a more robust value type .WHICH
。
使用数组作为散列键的简单方法
my %hash;
%hash{ [1,2,3].perl } = 'foo';
say %hash{ [1,2,3].perl }; # displays 'foo'
.perl
将其参数转换为该参数的 string of Perl 6 code that's a 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 讨论使用前缀 ~
实现更有限但类似的效果的替代方法 and/or 尝试在下面的评论中了解我与 Liz 的交流。