hashmap - 意外的哈希扁平化
问题描述
我正在寻找解释为什么这两个数据结构不相等:
$ perl6 -e 'use Test; is-deeply [ { a => "b" } ], [ { a => "b" }, ];'
not ok 1 -
# Failed test at -e line 1
# expected: $[{:a("b")},]
# got: $[:a("b")]
Hashes 和 Arrays 中的尾随逗号是没有意义的,就像在 P5 中一样:
$ perl6 -e '[ 1 ].elems.say; [ 1, ].elems.say'
1
1
但是没有它,哈希会以某种方式丢失,并且会被展平为一对数组:
$ perl6 -e '[ { a => "b", c => "d" } ].elems.say;'
2
我怀疑一些伟大的列表重构法则在这里适用,但我想得到更详细的解释来理解这种扁平化背后的逻辑。
解决方案
就像在 P5 中一样,哈希和数组中的尾随逗号是没有意义的
不,这不是毫无意义的:
(1 ).WHAT.say ; # (Int)
(1,).WHAT.say ; # (List)
Great List Refactor 中最大的简化是切换到用于迭代功能的单参数规则1。也就是说,像 afor
或数组和散列组合器(和下标)这样的特性总是得到一个参数。这确实是您原始示例的情况。
单个参数可能 - 通常是 - 一个值列表,甚至可能是一个列表列表等,但顶级列表仍然是迭代功能的单个参数。
如果迭代功能的单个参数扮演Iterable角色(例如列表、数组和散列),那么它就是迭代的。(这是一个不精确的公式;请参阅我对“何时调用迭代器方法?”的回答以获得更精确的答案。)
所以这里要注意的关于额外逗号的关键是,如果单个参数没有起到Iterable
作用,例如,那么1
最终结果与参数是一个只包含那个值的列表完全相同(即1,
) :
.perl.say for {:a("b")} ; # :a("b") Iterable Hash was iterated
.perl.say for {:a("b")} , ; # {:a("b")} Iterable List was iterated
.perl.say for 1 ; # 1 Non Iterable 1 left as is
.perl.say for 1 , ; # 1 Iterable List was iterated
“在声明单个元素列表时保留结构 [除了] 使用尾随逗号”(参见下面的注释),即
停止像往常一样迭代单个Iterable
值,是通过item使用 a 对其进行化$
:
my @t = [ $[ $[ "a" ] ] ];
@t.push: "b";
@t.perl.say; # [[["a"],], "b"]
1在 a 的情况下,迭代用于获取要传递给某些代码的值for
;在作曲家的情况下,让值成为正在构造的数组/哈希的元素;在下标的情况下获取索引切片;等等其他迭代功能。
推荐阅读
- node.js - Node.js + MongoDB - findOne() 返回一个字段不起作用
- c# - 如何在Castle Windsor中批量注册没有BasedOn方法的接口?
- reactjs - 如何在反应中正确获得axios响应?
- linux - 如何从函数调用值到shell脚本
- javascript - 在javascript中捕获网页上的键盘输入
- ios - 当我单击 xcode 中的单元格时,如何在 rightBarButtonItem 中放置不同的图像?
- dart - 使用多个 Dart SDK 版本的推荐方法是什么?
- angular - 使用 fileuri 无法使用离子图像预览
- java - 从 JSON/String 文件中获取特定的 JSON 属性
- javascript - 如何在使用 pywb 归档时单击带有 selenium 的按钮