What does duckmap really do?

谁说我不能喝 提交于 2019-12-10 02:18:57

问题


From 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.

But then:

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 behaves pretty much as expected, but I can't really make any sense of what duckmap is doing.

This question is related to this issue in perl6/doc. It can be solved with "They couldn't be more different", but I would like to find some examples where they do the same, and when they don't, try and understand really what's going on.


回答1:


The duck in duckmap refers to duck-typing; that is “if it walks like a duck and talks like a duck, it must be a duck.”

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

(use fatal is there so that the "a".Int failure object becomes a thrown exception, so that duckmap catches it and returns the original data instead)

This is useful for changing small portions of the input without having to specially deal with every possible input.

> 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"]

There are more differences between duckmap and the other maps, but they all are there for this basic premise.


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

(Note that you can't do the above at all with deepmap, as it goes too deep)
In order to get the same behaviour out of map, would require potentially much more work.




回答2:


duckmap goes deep only if &block can not be called on Array. $_ can be Array in -> $_ { $_² }.

Try

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

There, duckmap goes deep.



来源:https://stackoverflow.com/questions/50201995/what-does-duckmap-really-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!