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

ссылка на оригинал статьи http://habrahabr.ru/post/254029/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *