Хэл Фултон - Программирование на языке Ruby
- Название:Программирование на языке Ruby
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2007
- Город:Москва
- ISBN:5-94074-357-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Хэл Фултон - Программирование на языке Ruby краткое содержание
Ruby — относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов.
Книга является полноценным руководством по Ruby — ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа «как сделать то или иное в Ruby». В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии.
Издание предназначено для программистов самого широкого круга и самой разной квалификации, желающих научиться качественно и профессионально работать на Ruby.
Программирование на языке Ruby - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Во-первых, байты, входящие в состав многобайтовых символов, тщательно подобраны. Нулевой байт (ASCII 0) никогда не встречается в качестве n-ого байта в последовательности (где n > 1); то же самое справедливо для таких распространенных символов, как косая черта (обычно используется для разделения компонентов пути к файлу). На самом деле никакой байт из диапазона 0x00-0x7F не может быть частью никакого другого символа.
Второй байт многобайтового символа однозначно определяет, сколько байтов за ним следует. Этот второй байт всегда выбирается из диапазона от 0хС0
до 0хF0
, а следующие за ним — из диапазона от 0x80
до 0xBF
. Таким образом, схема кодирования свободна от состояния и позволяет восстанавливать пропущенные или искаженные байты.
UTF-8 — одна из самых распространенных и гибких кодировок в мире. Она применяется с начала 1990-х годов и является кодировкой по умолчанию XML-документов. В этой главе мы будем иметь дело главным образом именно с UTF-8.
4.2. Кодировки в пост-ASCII мире
«Век ASCII» прошел, хотя не все еще осознали этот факт. Многие допущения, которые программисты делали в прошлом, уже несправедливы. Нам необходимо новое мышление.
Есть две идеи, которые, на мой взгляд, являются основополагающими, почти аксиомами. Во-первых, строка не имеет внутренней интерпретации. Она должна интерпретироваться в соответствии с некоторым внешним стандартом. Во-вторых, байт и символ — не одно и то же; символ может состоять из одного или нескольких байтов. Есть и другие уроки, но это самое важное.
Эти факты оказывают на программирование тонкое влияние. Рассмотрим сначала, как следует работать с символьными строками по-современному.
4.2.1. Библиотека jcode и переменная $KCODE
Чтобы использовать в Ruby разные наборы символов, вы должны знать о глобальной переменной $KCODE
, от значения которой зависит поведение многих системных методов, манипулирующих строками. (Кстати говоря, буква K — напоминание о кандзи, одной из иероглифических азбук в японском языке.) Эта переменная принимает одно из пяти стандартных значений, каждое из которых представлено одной буквой, неважно — строчной или прописной (ASCII и NONE — одно и то же).
a ASCII
n NONE (ASCII)
е EUC
s SJIS
u UTF-8
Для ясности можно пользоваться и полными названиями (например, $KCODE ="UTF-8"
). Важен только первый символ.
О кодировке ASCII мы уже знаем. EUC и Shift-JIS (SJIS) нам малоинтересны. Мы сосредоточимся на значении UTF-8.
Установив значение $KCODE
, вы задаром получаете весьма богатую функциональность. Например, метод inspect
(он автоматически вызывается при обращении к методу p
для печати объекта в читаемом виде) обычно учитывает текущее значение $KCODE
.
$KCODE = "n"
# Для справки: французское слово "épée"
# обозначает разновидность меча (sword).
eacute = ""
eacute << 0303 << 0251 # U+00E9
sword = eacute + "p" + eacute + "e"
p eacute # "\303\251"
p sword # "\303\251p\303\251e"
$KCODE = "u"
p eacute # "é"
p sword # "épée"
Регулярные выражения в режиме UTF-8 тоже становятся несколько «умнее».
$KCODE = "n"
letters = sword.scan(/(.)/)
# [["\303"], ["\251"], ["p"], ["\303"], ["\251"], ["e"]]
puts letters.size # 6
$KCODE = "u"
letters = sword.scan(/(.)/)
# [["é"], ["p"], ["é"], ["e"]]
puts letters.size # 4
Библиотека jcode
предоставляет также несколько полезных методов, например jlength
и each_char
. Рекомендую включать эту библиотеку с помощью директивы require
всякий раз, как вы работаете с кодировкой UTF-8.
В следующем разделе мы снова рассмотрим некоторые типичные операции со строками и регулярными выражениями. Заодно поближе познакомимся с jcode
.
4.2.2. Возвращаясь к строкам и регулярным выражениям
При работе с UTF-8 некоторые операции ничем не отличаются. Например, конкатенация строк выполняется так же, как и раньше:
"éр" + "éе" # "épée"
"éр" << "éе" # "épée"
Поскольку UTF-8 не имеет состояния, то для проверки вхождения подстроки тоже ничего специально делать не нужно:
"épée".include?("é") # true
Однако при написании интернациональной программы некоторые типичные допущения все же придется переосмыслить. Ясно, что символ больше не эквивалентен байту. При подсчете символов или байтов надо думать о том, что именно мы хотим сосчитать и для чего. То же относится к числу итераций.
По общепринятому соглашению, кодовую позицию часто представляют себе как «программистский символ». Это еще одна полуправда, но иногда она оказывается полезной.
Метод jlength
возвращает число кодовых позиций в строке, а не байтов. Если нужно получить число байтов, пользуйтесь методом length
.
$KCODE = "u"
require 'jcode'
sword = "épée"
sword.jlength # 4
sword.length # 6
Такие методы, как upcase
и capitalize
, обычно неправильно работают со специальными символами. Это ограничение текущей версии Ruby. (Не стоит считать ошибкой, поскольку получить представление слова с первой прописной буквой довольно трудно; такая задача просто не решается в схеме интернационализации Ruby. Считайте, что это нереализованное поведение.)
$KCODE = "u"
sword.upcase # "ÉPÉE"
sword.capitalize # "épée"
Если вы не пользуетесь монолитной формой, то в некоторых случаях метод может сработать, поскольку латинские буквы отделены от диакритических знаков. Но в общем случае работать не будет — в частности, для турецкого, немецкого, голландского и любого другого языка с нестандартными правилами преобразования регистра.
Возможно, вы думаете, что неакцентированные символы в некотором смысле эквивалентны своим акцентированным вариантам. Это почти всегда не так. Здесь мы имеем дело с разными символами. Убедимся в этом на примере метода count
:
$KCODE = "u"
sword.count("e") # 1 (не 3)
Но для составных (не монолитных) символов верно прямо противоположное. В этом случае латинская буква распознается.
Метод count
возвращает сбивающий с толку результат, когда ему передается многобайтовый символ. Метод jcount
ведет себя в этом случае правильно:
$KCODE = "u"
sword.count("eé") # 5 (не 3)
sword.jcount("eé") # 3
Существует вспомогательный метод mbchar?
, который определяет, есть ли в строке многобайтовые символы.
$KCODE = "u"
sword.mbchar? # 0 (смещение первого многобайтового символа)
"foo".mbchar? # nil
В библиотеке jcode
переопределены также методы chop
, delete
, squeeze
, succ
, tr
и tr_s
. Применяя их в режиме UTF-8, помните, что вы работаете с версиями, «знающими о многобайтовости». При попытке манипулировать многобайтовыми строками без библиотеки jcode
вы можете получить странные или ошибочные результаты.
Интервал:
Закладка: