Карты, вложенные карты и контекст приемника - PullRequest
0 голосов
/ 19 мая 2018

Этот код ничего не возвращает

<foo bar ber>.map: { $^a.comb.map: { $^b.say}};

Он содержит две вложенные карты, обе в контексте приемника .это не должно работать, потому что список, утопленный в контекст приемника, является неоперативным .

Однако это работает:

<foo bar ber>.map: *.say; # OUTPUT: «foo␤bar␤ber␤»

, и это сновасписок в контексте приемника.Так почему же это работает?

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

A map не возвращает List, а скорее Seq.Seq - это последовательность значений Iterable в один прием, и в контексте приемника она будет выполнять итерацию своего базового итератора и отбрасывать полученные значения.Вот почему map в контексте приемника будет повторяться, но только на один уровень глубины.Добавьте .flat, чтобы поглотить даже внутренние значения (сведя их в одну последовательность верхнего уровня):

<foo bar ber>.map({ $^a.comb.map: { $^b.say}}).flat # OUTPUT: «f␤o␤o␤b␤a␤r␤b␤e␤r␤»

A List действительно не будет повторять свои значения в контексте приемника, потому что List - это структура данных, которая запоминает даже ленивые значения, чтобы их можно было многократно индексировать.Действительно, выполнение:

(<foo bar ber>.map: *.say).list;

Не производит вывода, потому что Seq был приведен к List, который ничего не делает в контексте приемника.

Очень мало встроенных операций надПовторяемые данные возвращают List, так как было бы преждевременным обязательством сохранять данные.Часто бывает полезно объединить такие операции в цепочку и получить поток данных через них по одному элементу, а не хранить их в памяти на каждом промежуточном этапе.Это то, что позволяет Seq, и почему так много вещей возвращают его вместо List.

0 голосов
/ 19 мая 2018

Я думаю, это потому, что только последний оператор map является не затонувшим:

class A {
    method sink() {
        say "sunk"
    }
}
<foo bar ber>.map: { A.new }     # doesn't show 'sunk'
A.new;                           # shows 'sunk' once
<foo bar ber>.map: { A.new; 1 }  # shows 'sunk' 3x

Так что внутренний map неполучить потоп, и, следовательно, не работает, потому что это sink-all на внутренней карте (которая вызывается на итераторе с помощью метода sink), что делает вещи.

...