duckmap 到底做了什么?

What does duckmap really do?

来自the documentation

duckmap will apply &block on each element and return a new list with defined return values of the block. For undefined return values, duckmap will try to descend into the element if that element implements Iterable.

但是然后:

my $list = [[1,2,3],[[4,5],6,7]];

say $list.deepmap( *² ); # [[1 4 9] [[16 25] 36 49]]
say $list.duckmap( *² ); # [9 9]

deepmap 的行为与预期的差不多,但我无法真正理解 duckmap 在做什么。

此问题与 this issue in perl6/doc 有关。它可以用 "They couldn't be more different" 来解决,但我想找到一些例子,他们做同样的事情,当他们不做的时候,试着真正理解发生了什么。

duckmap 只有当 &block 不能在 Array 上调用时才会深入。 $_ 可以是 -> $_ { $_² }.

中的数组

尝试

say $list.duckmap( -> Int $_ {$_²} ); #returns [[1 4 9] [[16 25] 36 49]]

在那里,duckmap深入。

duckmap中的duck指的是duck-typing;那就是“如果它走路像鸭子,说话像鸭子,它一定是鸭子。”

> say [1,2.2,"3.4",4,"a"].duckmap(-> Str $_ { use fatal; .Int }).perl
[1, 2.2, 3, 4, "a"]

use fatal 是为了让 "a".Int 失败对象变成抛出的异常,所以 duckmap 捕获它并 returns 原始数据)

这对于更改输入的一小部分很有用,而不必专门处理每个可能的输入。

> say [1,2.2,"3.4",4,"a"].map(-> $_ { $_ ~~ Str ?? .Int // .self !! .self }).perl
[1, 2.2, 3, 4, "a"]
> say [1,2.2,"3.4",4,"a"].deepmap(-> $_ { $_ ~~ Str ?? .Int // .self !! .self }).perl
[1, 2.2, 3, 4, "a"]

duckmap和其他map之间的区别更多,但都是为了这个基本前提。


> [ [<a b c>], [1,2,3], [[4,5,6],] ].duckmap(-> @_ where .all ~~ Int { @_.Str } ).perl
[["a", "b", "c"], "1 2 3", ["4 5 6"]]

> [ [<a b c>], [1,2,3], [[4,5,6],] ].map(-> @_ { @_.all ~~ Int ?? @_.Str !! @_.self } ).Array.perl
[["a", "b", "c"], "1 2 3", [[4, 5, 6],]] # doesn't match, as map is one level deep

(请注意,您不能使用 deepmap 执行上述操作,因为它太深了)
为了从 map 中获得相同的行为,可能需要做更多的工作。