意外的哈希扁平化

Paw*_*bkr 7 hashmap perl6

我正在寻找解释为什么这两个数据结构不相等:

$ 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")]
Run Code Online (Sandbox Code Playgroud)

哈希和数组中的尾随逗号就像在P5中一样没有意义:

$ perl6 -e '[ 1 ].elems.say; [ 1, ].elems.say'
1
1
Run Code Online (Sandbox Code Playgroud)

但是如果没有它,Hash会以某种方式丢失并且变得扁平化为对数组:

$ perl6 -e '[ { a => "b", c => "d" } ].elems.say;'
2
Run Code Online (Sandbox Code Playgroud)

我怀疑一些Great List Refactor法律适用于此,但我想得到更详细的解释,以了解这种扁平化背后的逻辑.

rai*_*iph 6

哈希和数组中的尾随逗号就像在P5中一样没有意义

不,这不是没有意义的:

(1 ).WHAT.say ; # (Int)
(1,).WHAT.say ; # (List)
Run Code Online (Sandbox Code Playgroud)

Great List Refactor的大简化是切换到迭代特征1 的单个参数规则.也就是说,像a 或数组和哈希作曲家(和下标)这样的功能总是得到一个参数.这确实是你原来的例子.for

单个参数可能是 - 通常是 - 一个值列表,甚至可能是列表列表等,但顶级列表仍然是迭代特征的单个参数.

如果迭代特性的单个参数执行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
Run Code Online (Sandbox Code Playgroud)

"声明单个元素列表时使用尾随逗号保留结构[除了]之外的典型方式"(请参阅​​下面的注释),即 停止Iterable按正常情况迭代的单个值,是通过项目对其进行项目$:

my @t = [ $[ $[ "a" ] ] ];
@t.push: "b";
@t.perl.say; # [[["a"],], "b"]
Run Code Online (Sandbox Code Playgroud)

1迭代用于获取在a的情况下传递给某些代码的值for; 获取值以成为在作曲家的情况下构造的数组/散列的元素; 在下标的情况下获得索引切片; 等等其他迭代功能.