Транслитерация в Perl6

«Транслитерация» означает замена символов. Именно этим и занимается метод Str.trans

say "GATTACA".trans( "TCAG" => "0123" );  # выводит "3200212\n" 

Люди, знакомые с Perl 5 или с оболочкой Unix распознают в этом tr/tcag/0123/, а для остальных поясним: каждая буква T заменяется на 0, каждая C на 1, и так далее. Две строки, TCAG и 0123, предоставляют алфавиты, которые надо взаимозаменять.

Это можно использовать для скорости при реализации разных операций. Например, простая функция, «шифрующая» текст методом ROT-13 (замена символа тем, что стоит через 13 позиций от него):

sub rot13($text) { $text.trans( "A..Za..z" => "N..ZA..Mn..za..m" ) } 

.trans раскрывает диапазоны…, поэтому «n..z» будет означать «nopqrstuvwxyz». Таким образом, функция rot13 заменит конкретные части алфавита ASCII другими частями.

В Perl 5 вместо двух точек… используется тире — , но в Perl 6 мы решили, что две точки лучше обозначают концепцию «промежутка» – в языке, в регулярках и в транслитерации.

Метод .trans не меняет $text, а только возвращает новое значение. Так принято в Perl 6 – мы предлагаем методы без побочных эффектов. Но при необходимости подобное поведение можно определить через .=:

$kabbala.=trans("A..Ia..i" => "1..91..9"); 

Это работает и для всех остальных методов. Программистам всё же рекомендуется писать библиотеки, поддерживающие первый метод, и тогда наш мир будет светлее и лучше.

Но это не был бы Perl 6, не содержи .trans скрытой силы, превышающей простое tr///. Вот что он ещё делает.

Допустим, нам надо экранировать некоторые символы для HTML, то есть заменить их согласно списку:

    & => &     < => <     > => > 

Можно ограничиться регулярками. Но может так получится, что вы на этом шаге застрянете в бесконечном цикле (& => & => &amp; => …). Но проблема даже не в этом, а в том, что вы будете заниматься сшиванием кусков строк, вместо того, чтобы охватить задачу целиком на более высоком уровне. Кроме того, хотелось бы, чтобы метод работал примерно так:

  маска => вещь   маскарад => мероприятие 

Если сначала будет выполняться первая замена, то на долю второй ничего не останется – и результат будет неправильным. Обычно нам надо менять более длинные строки в первую очередь.

И такое поведение даёт нам .trans в Perl 6. Это его скрытое оружие – передача пары массивов, а не просто пары строк. Для экранирования символов нужно всего лишь указать:

my $escaped = $html.trans(     [ '&',     '<',    '>'    ] =>     [ '&', '<', '>' ] ); 

и все эти нетривиальные, но нудные задачи по замене символов в правильном порядке без выпадания в вечный цикл будут решены за нас.

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

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

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