Помните ли вы статью про оператор последовательностей в Perl 6?
Последним аргументом он принимает ограничение, которое останавливает генерацию последовательности. К примеру
1, 2, 4 ... 32; # 1 2 4 8 16 32
1, 2, 4 ... * > 10; # 1 2 4 8 16
В первом случае используется числовое сравнение. Во втором запись * > 10 интерпретируется как замыкание -> $x { $x > 10 }.
Оператор последовательностей выполняет «волшебное» сравнение в зависимости от типа соответствия. Это сравнение называется «умным соответствием» («smartmatching»), и эта концепция появляется во многих местах Perl 6. Примеры:
# после ключевого слова 'when':
given $age {
when 100 { say "Поздравляю!" }
when * < 18 { say "Молодой ещё" }
}
# после 'where':
subset Even of Int where * %% 2;
# непосредственно с оператором smartmatch:
if $input ~~ m/^d+$/ {
say "$input – целое число";
}
# аргументы для grep(), first() и т.д.:
my @even = @numbers.grep: Even;
С правой стороны от ~~ и после when и where сравниваемое значение берётся из $_. Это позволяет нам создавать конструкции, работающие с $_, такие, как регулярки, созданные через m/.../ и .method_call.
Примеры использования оператора:
# равен ли тип переменной Str?
$foo ~~ Str
# равно ли это 6?
$foo ~~ 6
# или это "bar"?
$foo ~~ "bar"
# соответствует ли шаблону?
$foo ~~ / w+ '-' d+ /
# Находится ли между 15 и 25?
$foo ~~ (15..25)
# вызов замыкания
$foo ~~ -> $x { say 'ok' if 5 < $x < 25 }
# Является ли это массивом из 6 элементов, у которого каждый нечётный элемент равен 1?
$foo ~~ [1, *, 1, *, 1, *]
Подробная таблица для оператора.
Заметьте, что в отличие от Perl 5, в Perl 6 smartmatching – единственный способ сравнить что-то с регуляркой, особого оператора для этого нет. Кроме того, хотя большинство операций smartmatching возвращает Bool, сравнение с регуляркой возвращает объект Match. Который, при этом, правильно ведёт себя в булевом контексте.
Ладненько, а как это использовать не со встроенными типами, а со своими собственными классами? Для этого надо написать особый метод, ACCEPTS. Допустим, есть у нас старый добрый класс Point:
class Point {
has $.x;
has $.y;
method ACCEPTS(Positional $p2) {
return $.x == $p2[0] and $.y == $p2[1]
}
}
Понятно? Посмотрим, как это работает:
my $a = Point.new(x => 7, y => 9);
say [3, 5] ~~ $a; # Bool::False
say (7, 9) ~~ $a; # Bool::True
Теперь Perl 6 может выполнять именно то, что вы имели в виду, даже с вашими собственными классами.
Автор: SLY_G