Курс языка программирования Raku / Продвинутый уровень / Операторы / Метаоператоры

Перекрёстные, гипер- и отрицающие

Кроме свёртки и zip в Raku есть ещё несколько метаоператоров. Три из них стоит знать уже сейчас.

Перекрёстный — X

Перекрёстный метаоператор X сочетает каждый элемент одного списка с каждым элементом другого — это декартово произведение:

say <a b> X <1 2>; # ((a 1) (a 2) (b 1) (b 2))

Как и zip, он может обернуть оператор, чтобы подействовать на каждую пару. X~ соединяет каждую пару в строку, а X* перемножает:

say <a b> X~ <1 2>;         # (a1 a2 b1 b2)
say (1, 2, 3) X* (10, 100); # (10 100 20 200 30 300)

Если zip проходит по двум спискам в ногу, то перекрёстный оператор сочетает их всеми возможными способами.

Гипероператор — »…«

Гипероператор применяет оператор к каждому элементу списка. Оператор заключается в угловые стрелки »…« (или в ASCII-запись >>…<<). С двумя списками он работает поэлементно, как zip; а если с одной стороны стоит одно значение, оно растягивается на весь список:

say (1, 2, 3) »+» (10, 20, 30); # (11 22 33)
say (1, 2, 3) »*» 2;            # (2 4 6)

Стрелки не обязаны смотреть в одну сторону, и их направление решает, что произойдёт, если длины списков не совпадают: остриё, направленное на список, разрешает повторять этот список, подгоняя его под другой. В ASCII-записи <</>> возможны четыре сочетания:

  • >>op<< — ни одна сторона не растягивается; списки должны быть одной длины, иначе будет ошибка;
  • >>op>>правый список повторяется, подгоняясь под левый;
  • <<op<<левый список повторяется, подгоняясь под правый;
  • <<op>>более короткий список повторяется, подгоняясь под более длинный.
say (1, 2, 3, 4) <<+>> (10, 20); # (11 22 13 24)  — 10, 20 повторяется как 10, 20, 10, 20

Есть и унарная форма, которая вызывает метод у каждого элемента. >>.uc переводит каждую строку в верхний регистр:

say <raku perl>>>.uc; # (RAKU PERL)

Гипероперации к тому же означают, что работа может выполняться параллельно — со связанным методом .hyper вы встретитесь позже, в разделе о конкурентном программировании.

Отрицающий — !

Если поставить ! перед оператором сравнения, его результат меняется на противоположный. Привычный != (не равно) — это ровно тот же метаоператор, применённый к ==, и точно так же он работает с другими логическими операторами, например eq и %%:

say 3 != 4;      # True
say 'a' !eq 'b'; # True  — не равны как строки
say 5 !%% 2;     # True  — 5 не делится на 2

Коротко говоря, $a !op $b — это просто более аккуратная запись для !($a op $b).

И так задумано. В отличие от нарочито минималистичного языка вроде эсперанто, который стремится дать один правильный способ выразить каждую мысль, Raku охотно предлагает несколько — поэтому отрицающий !eq соседствует с отдельным оператором ne, и означают они ровно одно и то же:

say 'a' ne 'b'; # True — та же проверка, что и 'a' !eq 'b'

Практика

Пройдите 1 тест по содержанию этой темы.

Навигация по курсу

Метаоператоры zip   |   Тест — Гипер- и перекрёстные операторы


💪 Или перейдите сразу к упражнениям этого раздела.