duckmap
将在每个元素上应用&block
并返回一个新的列表,其中包含块的定义返回值。对于未定义的返回值,如果该元素实现duckmap
,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有关。它可以通过“它们无法更加不同”来解决,但我想找到一些例子,他们也会这样做,当他们不这样做时,试着去了解真正发生的事情。
duckmap
中的鸭子指的是鸭子打字;那就是“如果它像鸭子一样走路,像鸭子一样说话,那一定是鸭子。”
> 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
捕获它并返回原始数据)
这对于更改输入的一小部分非常有用,而无需专门处理每个可能的输入。
> 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
s之间存在更多差异,但它们都存在于这个基本前提中。
> [ [<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
中获得相同的行为,可能需要更多的工作。
duckmap
只有在无法在阵列上调用&block
时才会深入。 $_
可以在-> $_ { $_² }
中阵列。
尝试
say $list.duckmap( -> Int $_ {$_²} ); #returns [[1 4 9] [[16 25] 36 49]]
在那里,duckmap
深入。