Что на самом деле делает Duckmap?

Из документации

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 делает.

Этот вопрос связан с этой проблемой в perl6 / doc. Ее можно решить, сказав: «Они не могут быть более разными», но я хотел бы найти несколько примеров, где они делают то же самое, а когда нет, попытайтесь понять, что действительно происходит.


person jjmerelo    schedule 06.05.2018    source источник
comment
[9,9] возводит в квадрат количество элементов в подсписках. Попробуйте добавить или удалить элемент для проверки. Помимо других полезных ответов, усилия по документации могут найти интересный S32-list / duckmap.t: github.com/perl6/roast/blob/master/S32-list/duckmap.t   -  person mr_ron    schedule 06.05.2018


Ответы (2)


утка в 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, но все они существуют для этой основной предпосылки.


> [ [<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, потенциально потребуется гораздо больше работы.

person Brad Gilbert    schedule 06.05.2018

duckmap углубляется только в том случае, если &block не может быть вызван в массиве. $_ может быть массивом в -> $_ { $_² }.

Пытаться

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

Там duckmap идет глубоко.

person wamba    schedule 06.05.2018