21. Определение длины строки в Perl 6

Perl 6 сразу и без обиняков считает исходный текст программы сохраненным в UTF-8. Да и вообще, поддержка юникода в Perl 6 очен радует. Сегодня посмотрим, как узнать длину строки.

Решение в лоб, знакомое по опыту Perl 5, не работает. На попытку вызвать функцию length компилятор выдает инструкцию воспользоваться новыми возможностями:

Undeclared routine:
    length used at line 1. Did you mean 'elems', 'chars', 'codes'?

elems, chars и codes

Метод elems относится скорее к массивам, чем к строкам. А вот с chars и codes давайте разберемся.

Метод символов в строке:

say 'hello'.chars;  # 5
say 'café'.chars;   # 4
say 'привет'.chars; # 6
say '嗨'.chars;     # 1

Все отлично работает независимо от языка и наличия диакритических знаков.

Метод codes возвращает число кодовых позиций, необходимых для записи строки. Во многих случаях результат будет совпадать с тем, что возвращает chars. Если же юникодный символ собран из таких частей, которые невозможно воспроизвести в одиночном символе (например, буква плюс какой-то хитрый диакритический знак, который в известных языках не применяется с данной буквой), то Perl не сможет привести этот символ к каноническому виду и, соответственно, chars покажет 1, а codes — 2.

Длина в байтах

Если нужно определить длину строки в байтах, то просто вызвать метод, например, bytes, не получится. Хотя скорее всего вы имели в виду кодировку UTF-8, Perl 6 желает услышать это явно. Действительно, при разном кодировании одна и та же строка занимет разное число байтов. Вот как это делается:

say 'hello'.encode('UTF-8').bytes;  # 5
say 'café'.encode('UTF-8').bytes;   # 5
say 'привет'.encode('UTF-8').bytes; # 12
say '嗨'.encode('UTF-8').bytes;     # 3

В UTF-16, например, число байт будет отличаться:

say 'hello'.encode('UTF-16').bytes;  # 10
say 'café'.encode('UTF-16').bytes;   # 8
say 'привет'.encode('UTF-16').bytes; # 12
say '嗨'.encode('UTF-16').bytes;     # 2

Разумеется, при попытке посчитать байты в Latin-1, часть строк не сможет быть конвертирована:

$ perl6 -e'say "ю".encode("Latin-1")'
Error encoding Latin-1 string: could not encode codepoint 1102
  in block  at -e line 1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s