代码之家  ›  专栏  ›  技术社区  ›  Hunter McMillen zellus

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

  •  10
  • Hunter McMillen zellus  · 技术社区  · 7 年前

    在哈希文档中,关于 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
    

    有可能做到这一点吗?

    2 回复  |  直到 5 年前
        1
  •  8
  •   Elizabeth Mattijsen    5 年前

    这个 [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
    

    请注意 哪一个 那些看似相同的数组的值是不同的。 那是因为 大堆 s是可变的。像 List 可能是这样,所以这不会真的起作用。

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

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

    请注意,这两个 哪一个 es是相同的。所以你可以这样写:

    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

        2
  •  3
  •   Community CDub    4 年前

    如果出于某种原因,您真的只对使用对象哈希感兴趣,请在此处参考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的交流。