...

четверг, 26 марта 2015 г.

[Перевод] Perl 6 и умное соответствие

Помните ли вы статью про оператор последовательностей в 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 может выполнять именно то, что вы имели в виду, даже с вашими собственными классами.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий