Pull to refresh

Perl 6 и умное соответствие

Perl *Programming *
Translation
Original author: ttjjss
Помните ли вы статью про оператор последовательностей в 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 может выполнять именно то, что вы имели в виду, даже с вашими собственными классами.
Tags: perl 6rakudosmartmatching
Hubs: Perl Programming
Total votes 11: ↑10 and ↓1 +9
Comments 2
Comments Comments 2

Popular right now