Курс по Raku / Напреднали / Оператори / Метаоператори

Кръстосани, хипер и отрицателни

Освен редукция и zip, Raku има и няколко други метаоператора. Три от тях заслужават внимание тук.

Cross — X

Метаоператорът cross 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 обхожда два списъка в крак, cross ги комбинира по всеки възможен начин.

Хипер — »…«

Хипер метаоператорът прилага оператор към всеки елемент от списък. Операторът е обвит в остри »…« (или 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 repeats to 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 метаоператори   |   Тест — Хипер и кръстосани


💪 Или преминете направо към упражненията в този раздел.