Что за зверь Ruby, и с чем его едят?

Руби (англ. Ruby — "Рубин") — интерпретируемый язык программирования высокого уровня. Обладает независимой от операционной системы реализацией многопоточности, строгой динамической типизацией, "сборщиком мусора" и многими другими возможностями, поддерживающими много разных парадигм программирования — прежде всего, объектную. Руби был задуман в 1993 году японцем Юкихиро Мацумото (по прозвищу Мац), стремившимся создать язык, совмещающий все качества других языков, способствующие облегчению труда программистов.
wikipedia.org

Человек создан для творчества, и я всегда знал, что люблю творить. Увы, я обделен талантом художника или музыканта. Зато я умею писать программы.
Я хочу, чтобы компьютер был моим слугой, а не господином, поэтому я должен уметь быстро и эффективно объяснить ему, что делать.
Юкихиро Мацумото


Мое знакомство с Ruby произошло не так давно во время одного из затянувшихся периодов творческого поиска. Много появилось интересных идей, кое- какие можно было быстро воплотить в код. Однако, приступив к работе, сразу же обнаружил, что на C++ достаточно сложно работать со строками и регулярными выражениями. Тут же замаячили новые идеи по реализации толковой библиотеки для работы с регулярными выражениями и обработки текстов... А на пару с этим — реализация основных строительных блоков будущих программ — итераторов, типизированных контейнеров, интеллектуальных указателей со сборщиком мусора и прочих полезных и нужных в работе каждого программиста вещей. Идея эта, зародившись в самых темных уголках моего подсознания, минуя всякие размышления, мгновенно воплотилась в дело. Когда некоторая часть проектной документации на библиотеки была готова, я с гордостью взглянул на плоды своих трудов. Среди наслоений иерархий классов, диаграмм деятельностей и прочих моделей уже очень отчетливо выделялся... остов будущего велосипеда с квадратными колесами. Писать то, что уже написано? Чудовищное безобразие! Благоразумие взяло верх, и я вновь предался грустным обломовским размышлениям. C++ никак не подходил для реализации моих задумок, потому что требовал приличной "обвески" библиотеками, которых у меня не было, а писать было лень. Вот требования, которым должен был соответствовать язык программирования, на котором я хотел бы писать:

1. Чем больше ООП — тем лучше.
2. Удобные средства языка для работы с текстом.
3. Большое количество свободных компонентов.
4. Поддержка современных тенденций в развитии программирования на уровне синтаксиса языка.
5. Наличие удобных инструментов разработки и отладки.
6. Достаточно частый выпуск новых версий языка и постоянное его обновление.
7. Хотелось бы, чтобы была межплатформенность.
8. И самое главное — максимальная скорость написания программ.

Вот список языков программирования, которые я проверил на соответствие этим требованиям: C++, C#, Java, Perl, Ruby. Сразу же выпал C++ по описанным выше причинам. Примерно по этой же причине не подошли и "двое из ларца": C# и Java. Эти языки слишком универсальные, в них не так удобно работать с текстами, как хотелось бы. Многие программируют на них так, как раньше программировали на C++: с циклами, условными операторами и большим количеством переменных. Тяжкое наследие ХХ века все еще довлеет над этими хорошими, в общем-то, языками. А кроме того, нету обширной, удобной и доступной базы кода. Такая база есть у Perl на cpan.org, а кроме того, он просто гениально подходит для работы с текстами. Но у него есть два важных недостатка: минимальная поддержка ООП и тормознувшее в последнее время развитие языка. Интерпретатор Perl 5 очень сложен и неряшливо спроектирован. В результате совершенно невозможно добавить в язык что-то новое. Создатели языка Perl поняли это уже давно и где-то с 1999 года разрабатывают новую, шестую, версию Perl с нуля на основе новой виртуальной машины Parrot. Эта виртуальная машина была спроектирована таким образом, чтобы выполнять не исходный код программы, как это делают сейчас интерпретаторы, а бинарный межплатформенный код, в который будет компилироваться программа. Главной изюминкой Parrot должна была стать возможность выполнять программы, написанные на разных языках, и использовать межъязыковые бинарные компоненты. Ничего не напоминает? Правильно, .NET. Увы, Microsoft реализовала эти идеи раньше и качественнее. Parrot перестал быть новинкой и теперь, похоже, угасает. А что же Ruby? Как он устоял в борьбе с .NET и Java? Оказывается, не просто устоял, а постепенно даже начинает с ними конкурировать. И для этого есть причины:

1. Ruby — интерпретируемый язык. А значит, у него отсутствует стадия компиляции, и изменения во время разработки проявляются мгновенно.
2. Программировать на Ruby легко: не надо объявлять переменные, переменные не типизированы. Кроме того, в Ruby реализовано автоматическое управление оперативной памятью.
3. Программировать на Ruby удобно: у целых чисел неограниченный диапазон, у объектов — хорошая модель обработки исключений. Все операторы возвращают значения (совсем как в Perl). Ruby поддерживает потоки как свои собственные, так и на уровне ядра ОС.
4. Программировать на Ruby быстро: в языке реализован широкий набор инструментов для работы с текстами, как в Perl, и существует
централизованное хранилище свободно доступного кода для Ruby, опять же, как для Perl.
5. На Ruby можно писать широкий класс приложений: консольные утилиты, утилиты с оконным пользовательским интерфейсом, сетевые сервисы и web- приложения.
6. Ruby наравне со Smalltalk реализует все новейшие концепции ООП. В Ruby все есть объект. Даже имя класса есть экземпляр класса Class.
7. Ruby имеет свои реализации для нескольких платформ, в том числе для Linux, Windows и MacOS X.

Все это, а также еще и многие другие свойства Ruby, которые я впоследствии опишу, сделали этот инновационный язык лучшим инструментом, позволяющим писать программы с максимальной скоростью. Повторюсь еще раз: при поисках инструмента главной для меня была скорость разработки программ с его помощью. Обратная сторона медали — не слишком высокая скорость выполнения программы. Вероятно, многие сейчас скажут, что абсолютно неоправданно приносить скорость исполнения в жертву скорости разработки. В некоторых случаях — да. Но в общем вам платят за результат, который достигнут в срок, или за качество, которое достигнуто с опозданием? Если скорость выполнения программы неидеальна, но приемлема, заказчика это устроит. Если же важна именно скорость исполнения программы, то это будет явно указано в требованиях. Поэтому код стоит писать быстро. Код должен быть понятным и красивым. Эти две сентенции сродни библейским заповедям для программиста. Ведь код гораздо чаще читают, чем пишут. Поэтому человек должен излагать свои мысли на понятном ему языке и автоматизировать их перевод на язык вычислительной машины. Для решения задачи человек должен использовать язык, оптимизированный под людей. А в задачу компилятора или интерпретатора входит грамотный перевод кода с этого языка на язык, понятный машине. И Ruby — большой шаг вперед в этом направлении. Что касается красоты исходного кода, написанного на Ruby, то здесь нельзя не упомянуть его японское происхождение. Там уже давно используются пять видов письма. Это четыре азбуки и иероглифы, которых, кстати, очень много. В Японии очень уважается искусство каллиграфии, и красиво написанный текст ценится. Вот несколько критериев красоты:

1. Для каждого конкретного случая используется своя система письма.
2. Чем более редкий иероглиф вы использовали в своем письме, тем более привлекательно оно для сердца японца.
3. Использовать иероглифы как можно чаще, ибо они более емкие.

Вот как отразилась культура японской письменности на Ruby.
1. Язык получился мультипарадигменным, то есть возможно написание программ в разных стилях.
2. Очень много специальных методов на все случаи жизни (эдакий аналог иероглифов), 80-90% из которых написаны пользователями языка.
3. Программирование в стиле C и даже C++ воспринимается как нечто чужеродное, но доминирования какого-либо одного стиля нет.
4. В процессе написания программы очень много внимания уделяется эстетичности письма (красоте программного кода).

В Ruby абсолютно все является объектом. Это очень важное утверждение: многие языки, в том числе Java, C#, VB.NET и т.д., декларируют то же самое. А главное — насколько глубоко проникла концепция ООП в структуру языка. В Ruby это проникновение тотальное. Даже лексемы программы в Ruby являются объектами. Зачем, например, в .NET и Java есть библиотека Math? Не лучше ли, используя инкапсуляцию и наследование, добавить функциональность математических методов прямо к тем объектам, данные которых обрабатываются? Я имею в виду экземпляры типов byte, short, int, long, decimal. Если бы было сделано именно так, то в коде нельзя было бы применить их непосредственно к числам. Скажем, для вычисления абсолютного значения числа -9 пришлось бы писать такой код:

int num = -9;
int absNum = num.abs();
Конечно, следующая строчка выглядит лучше:
int absNum = Math.abs(-9);
Но в ней нарушен принцип инкапсуляции: метод Math.abs() работает с данными, не принадлежащими классу Math. В Ruby вполне приемлемо написать так: absNum = -9.abs
И даже так, если понадобится:
len = "Hello, World!".length
i = "Hello, World!".index("o")
Ruby поддерживает самые новые тенденции в ООП и конструировании языков программирования. В результате на Ruby писать быстро, легко и удобно. Вот пример кода на Java, который реализует класс фильтра строк по их длине, добавляет 3 строки в список и выводит фильтрованный результат: public class Filter {
public static void main(String[] args) {
List list = new java.util.ArrayList();
list.add("Tim"); list.add("Ike"); list.add("Tina");
Filter filter = new Filter();
for (String item : filter.filterLongerThan(list, 3)) {
System.out.println( item );
}
}
public List filterLongerThan(List list, int length) {
List result = new ArrayList();
for (String item : list) {
if (item.length() <= length) { result.add( item ); }
}
return result;
}
}
Вот как то же самое делается на Ruby:
list = ['Tim', 'Ike', 'Tina']
list.select {|n| n.length > 3}.each {|n| puts n}

Программа на Java заняла 12 строк кода (не считая закрывающих фигурных скобок), программа на Ruby — 2. Т.е. для этой задачи Ruby оказался в 6 раз эффективнее! Проект Ruby оказался настолько привлекательным, что его реализовали для нескольких платформ: Windows, Unix, MacOS X, например. Но фанаты пошли дальше. Они сделали реализации языка для Java (JRuby) и .NET (Ruby.NET). Таким образом, тот же JRuby может использовать не только всю доступную базу кода для Ruby, но также и все компоненты Java, что делает Ruby еще более удобным. В своих тестовых программах я использовал оригинальную версию Ruby 1.8.5 и IDE FreeRIDE. Разумеется, для написания программ на Ruby можно использовать vim, emacs, eclipse, netbeans и многие другие инструменты. Но FreeRIDE понравилась мне своей простотой, удобством и скоростью работы. В любом случае код программы от IDE не зависит, и его можно написать в чем угодно.

Есть несколько способов установить Ruby. Во-первых, все крупные дистрибутивы как правило поставляются с соответствующим бинарным пакетом ruby1.8. Установить его можно так же, как и любой другой пакет этого дистрибутива, если он еще не установлен. Бинарные пакеты, как и исходники, можно взять на домашней странице Ruby: сайт Для установки Ruby из исходников можно скачать соответствующий архив (ruby1.8.xxx-tar.bz2), распаковать его (tar -xjf ruby1.8.xxx-tar.bz2), скомпилировать и установить (configure –prefix=/usr; make; make install; make install-doc). Команда make install-doc подготовит индекс документации по всем классам Ruby, доступным на локальной системе. Для установки Ruby на Windows тоже можно собрать его из исходников при помощи компилятора MinGW. Но я бы советовал взять бинарный установочный дистрибутив Ruby, который распакует и сконфигурирует Ruby. В нем сразу же поставляется и FreeRIDE, и библиотека GUI — Fx, и документация, и много чего еще. В среде Linux для запуска Ruby используется команда "ruby". В среде Windows есть две программы: ruby.exe, которая выполняется в консоли и предоставляет стандартные потоки ввода, вывода и ошибок, и программа rubyw.exe, которая запускается без консоли. Пользователям Windows будет более удобно пользоваться FreeRIDE, т.к. она предоставляет привычный доступ к Ruby и его документации без применения консоли. Пользователи Linux имеют более широкий выбор, т.к. не ограничены строгими идеологическими рамками оконного интерфейса и могут выбрать консольную утилиту.

Дмитрий Бушенко, nop@list.ru


Компьютерная газета. Статья была опубликована в номере 13 за 2007 год в рубрике программирование

©1997-2024 Компьютерная газета