Метаоператоры X и Z в Perl 6
Одна из новых идей Perl 6 — метаоператор. Это оператор, который можно скомбинировать с обычным оператором, изменив его поведение. Таких метаоператоров есть несколько штук, но в этой статье мы рассмотрим только X и Z.Оператор X вы могли видеть в роли инфиксного комбинирования. Он комбинирует списки, по элементу из каждого, во всех возможных комбинациях:
> say ((1, 2) X ('a', 'b')).perl
((1, «a»), (1, «b»), (2, «a»), (2, «b»))
Однако, запись infix:
> say ((1, 2) X, (10, 11)).perl ((1, 10), (1, 11), (2, 10), (2, 11)) Что произойдёт, если мы применим Х к другому инфиксному оператору? Например, к infix: <+>
> say ((1, 2) X+ (10, 11)).perl (11, 12, 12, 13) Вместо создания списка из всех возможных комбинаций, оператор применяет инфиксное сложение к спискам. Получается не список, а простой номер — сумма всех элементов этой комбинации.
Это работает со всеми инфиксными операторами. Возьмём объединение строк infix: <~>
> say ((1, 2) X~ (10, 11)).perl (»110»,»111»,»210»,»211») Или же числовое сравнение infix: <==>
> say ((1, 2) X== (1, 1)).perl
(Bool: True, Bool: True, Bool: False, Bool: False)
Теперь перейдём к метаоператору Z. Если вы уже встречали инфиксный оператор infix:
> say ((1, 2) Z, (3, 4)).perl ((1, 3), (2, 4)) > say ((1, 2) Z+ (3, 4)).perl (4, 6) > say ((1, 2) Z== (1, 1)).perl (Bool: True, Bool: False) Z, берёт по очереди каждый элемент каждого списка, затем работает сначала на первых элементах, потом на вторых, потом на третьих, и т.д. Останавливается он, когда доходит до конца списка, неважно, на какой стороне.
Также Z — ленивый, поэтому его можно применить к двум бесконечным спискам, и он выдаст столько результатов, сколько вы запросите. X может работать только когда бесконечный список будет слева.
Эти метаоператоры становятся мощными инструментами для совершения операций над индивидуальными элементами многих списков, связаны ли эти элементы между собой через индексы, как в случае Z, или же вам нужно проверить все возможные комбинации, как в случае с X.
Сделать ассоциативный массив из списков ключей и значений? Легко.
my %hash = @keys Z=> @values; Пройти по двум спискам одновременно:
for @a Z @b → $a, $b { … } Или по трём?
for @a Z @b Z @c → $a, $b, $c { … } Или нужно найти все возможные суммы, которые получатся от бросков трёх десятигранных кубиков:
my @d10 = 1 … 10; my @scores = (@d10 X+ @d10) X+ @d10; Чтобы изучить, как метаоператоры используются в реальных проектах, обратитесь к модулю для решения судоку.