What does duckmap really do?

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.


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.