Рубрика:
Программирование /
Программирование
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
Владимир Овсянников
Ruby – язык завтрашнего дня
Сегодня очень трудно не заметить ажиотаж вокруг языка программирования Ruby и фреймворка Ruby on Rails.
Ruby (в переводе с англ. – рубин) был задуман в 1993 году японцем Йукихиро Мацумото (Yukihiro Matsumoto), известным как Matz. Фанатик объектно-ориентированного программирования, он решил создать более объектный язык, нежели Python и более мощный, чем Perl.
Первая публичная версия Ruby вышла в 1995 году. Постоянно нарастала его популярность – ведь раз написав хотя бы одну программу на Ruby, писать на другом языке уже невозможно.
Но действительный прорыв в его распространении произошёл совсем недавно – в 2004 году, с появлением Ruby on Rails.
Что же такое Ruby?
Ruby – интерпретируемый язык программирования, поддерживающий много разных парадигм, в первую очередь объектную. Обладает автоматическим «сборщиком мусора» и строгой динамической типизацией, поддерживает многопоточность (*nix и независимая от ОС).
Иерархия базовых классов Ruby
Достоинства Ruby
- Объектом является абсолютно всё (имя класса – тоже объект). Как и в языке SmallTalk, понятие «примитивный тип» отсутствует (5 – объект класса Fixnum, 'ruby' – объект класса String, ... ). Даже части кода представлены тоже в виде объекта.
- Простой и последовательный синтаксис. Если вы хорошо говорите, читаете, пишете на английском, то для вас программа на Ruby – великолепная проза. Об этом хорошо изложено в книге «Why's (Poignant) Guide to Ruby» (http://poignantguide.net/ruby).
- Переменные не нужно объявлять, они не типизированы. Это касается и атрибутов класса.
- Поддержка основных принципов ООП (классы, методы, полиморфизм, инкапсуляция, примеси, методы-одиночки и т. д.).
- Блоки/Итераторы. Обычно эти понятия ассоциируются с языком программирования Python, однако Ruby ничем не уступает ему, а благодаря удивительной гибкости языка использование блоков стало более удобным.
- Неограниченный диапазон значений целых чисел. К сожалению, только целых.
- Обработка и перехват исключений. В этом плане язык схож с Java.
- Абсолютно всё возвращает значения. Методы, циклы, блоки и условные операторы if, unless, ?: возвращают последнее высчитанное значение, а условия and и or возвращают элемент, эквивалентный true, или первый элемент. Благодаря этому можно переменную приравнять, допустим, к циклу или конструкции case! Это удобно.
- Мощная поддержка правил (регулярных выражений). Заимствована у Perl с адаптацией под объектную парадигму.
Ruby – скриптовый язык, хотя имеется средство упаковки в .exe-файл для Win32 (http://exerb.sourceforge.jp), но при упаковке теряются некоторые преимущества программ, написанных на Ruby, такие как неограниченный диапазон целых чисел, кросплатформенность и некоторые другие.
Недостатки Ruby
- Скорость. Ruby действительно медленный, на что сам автор языка ответил следующим вопросом: «Вам платят за результат, который достигнут в срок или за качество, которое достигнуто с опозданием?» Также хочется отметить, что Java также очень медленный, но тем не менее им пользуются.
- Интерпретируемый язык. Это проблема для тех, кто пишет коммерческое ПО. Исходный код нельзя утаить даже в готовой программе – это действительно проблема.
- Невозможность управлять некоторыми процессами, например выделением памяти.
- Задание низкоуровневых структур данных не представляется возможным.
Установка
%port install ruby
При установке Ruby ставится irb (Interactive Ruby), именно им и будем пользоваться, запускается в консоли командой irb. (При установке на Windows, используя Ruby One-Click Installer, автоматически в переменную PATH добавляется директорий с бинарными кодами ruby.) Irb – интерактивный интерпретатор выражений Ruby, считываемых со стандартного ввода.
Для удобного и системонезависимого управления модулями/плагинами используется свой собственный формат пакетов (аналог rpm, deb, tgz, tbz, msi, ...) – rubygems. При использовании Ruby One-Click Installer rubygems можно установить сразу (предлагается на втором этапе установки выбрать необходимые компоненты, в том числе и rubygems), а вот для обладателей не Windows придется скачивать rubygems из Интернета и устанавливать отдельно. Установить модуль, например vcard (для работы с форматами vCard и iCalendar), можно командой:
# gem install vcard -y --remote
При этом модуль будет скачан из Интернета c соблюдением всех зависимостей (вам не стоит тратить время на поиски недостающих пакетов) и установлен на вашей машине. Подробнее о gem вы можете узнать, выполнив команду:
# gem --help
Типы данных
Как вы уже знаете, в Ruby всё – объекты тех или иных классов. Базовые классы:
- Fixnum (целые числа, меньше 231);
- Bignum (целые числа, больше 231);
- Float (дроби);
- String (строки);
- Array (индексные массивы);
- Hash (ассоциативные массивы);
- NilClass (nil/null);
- TrueClass (истина);
- FalseClass (ложь).
Ruby автоматически приводит к классу Numeric (в зависимости от значения – Float, Fixnum или Bignum) все объекты следующего вида:
- 2 – целое число;
- -3 – отрицательное целое число;
- 4.5 – число с плавающей точкой;
- 067 – восьмеричное число;
- 0b11 – двоичное число;
- 0xF0F0 – шестнадцатеричное число.
К классу String приводятся все объекты, записанные в апострофах или кавычках. Разница между этими двумя типами записи такая же, как в PHP, – в строках в кавычках происходит автозамена эскейп-последовательностей на соответствующие коды и записи вида #{объект} на значение объекта.
В Ruby есть два предопределённых объекта для обозначения логических значений («да»/«нет») – true (класс TrueClass) и false (класс FalseCalss).
Внимание: пустая строка, ноль, пустой массив… в логических операторах не являются аналогом false, его аналогом является только nil (класс NilClass), остальное – true.
Запись вида [el1, el2, el3] воспринимается как массив (индексный),а {'A'=>1, 'B'=>2, 'C'=>3} – как ассоциативный массив.
Так что следующие строки кода взаимозаменяемы:
arr1 = Array.new
arr2 = []
hash1 = Hash.new
hash2 = {}
Не hello word!
Начнём сразу с более интересных вещей, нежели вывод на экран тривиальной фразы. Метод class есть у всех объектов, и возвращает он класс объекта.
Введите «1.class» и нажмите <Enter>. Irb выведет:
значит, 1 – объект класса Fixnum, а вот, написав «(2**99).class», результат будет другой, т.к. целые числа более 231 являются объектами другого класса (** – возведение в степень).
Теперь напишем ещё более интересный пример:
Это значит, что класс Fixnum является объектом класса Class, который в свою очередь тоже объект класса Class.
Методы и атрибуты
Когда я программировал на C/C++, порой часто переписывал часть кода, которая обычно была связана с неприязнью использования глобальных переменных. Я в конце концов запутывался, какие переменные у меня локальные, какие глобальные, а какие – атрибуты класса. В Ruby это не проблема:
- Все имена классов и модулей должны начинаться с большой латинской буквы.
- Локальная переменная называется просто с маленькой буквы или знака подчёркивания.
- Все переменные объекта (они же атрибуты) со знака @, за которым следует строчная буква или знак подчёркивания.
- Переменные класса с @@, за которыми следует строчная буква или знак подчёркивания.
- Глобальные переменные со знаком «доллар» ($), за которым следует строчная буква или знак подчёркивания.
- Имена методов также именуются со строчной буквы или знака подчёркивания.
В Ruby можно создать методы с именами, например attr= и attr, которые будут вызываться:
obj.attr = 5
var = obj.attr
А благодаря акцессорам (attr_accessor, attr_reader и attr_writer) отпадает необходимость написания большинства методов для доступа к атрибутам объектов.
class MyFirstClass # создаём класс с именем MyFirstClass
attr_reader :first # заменится на def first; @first; end
attr_writer :second # заменится на def first=(v); @first = v; end
attr_accessor :tre # attr_reader + attr_writer
def initialize(attrs) # конструктор
@first = attrs[:first]
@second = attrs[:second]
@tre = attrs[:tre]
@end_attr = attrs[:end]
end
def end=(oth) # метод end = будет приравнивать @end_attr половине аргумента
@end_attr = oth/2.to_f # .to_f – принудительное приведение к Float
end
def end # метод end будет возвращать квадрат @end_attr
@end_attr**2 # методы возвращают последнее вычисленное значение или аргумент return
end
end
obj = MyFirstClass.new(:first=>'FIRST', :second=>2, :tre=>'ТРИ', :end=>5)
obj.first # => FIRST
obj.first = 'ПЕРВЫЙ' # => ОШИБКА: метод first=() не определён
obj.second = 'ДВА' # => ДВА
obj.second # => ОШИБКА: метод second() не определён
obj.tre = obj.tre*3 # => ТРИТРИТРИ
obj.end # => 25
obj.end = 11 # => 11
obj.end # => 30.25
Блоки
Блок – одна из главных особенностей Ruby, умение ими пользоваться – ключ к очень коротким, понятным и много делающим программам.
Думаю, вы не раз забывали закрыть открытый файл, очистить выделенную память, закрыть соединение с сервером...
Теперь это не проблема:
File.open('/tmp/tempfile', 'w') do |tmp|
tmp.write 'Bla-bla-bla'
end
Блок – анонимный метод. Он захватывает переменные окружающей среды. В примере тело блока ограничено do end, которые, кстати, могут быть заменены на { }. В качестве аргумента блоку передаётся объект класса File. После выхода из блока этой переменной не будет – она локальная для блока.
Блок сам откроет, а главное, закроет файл при необходимости.
Итераторы
Это те же блоки, но заточенные на работу с перечисляемыми объектами (объект является перечисляемым, если у него есть метод succ, возвращающий следующий элемент). То, что в древности люди делали циклами, теперь делают итераторы. Самое главное – что их много и каждый делает своё дело.
Для того чтобы вывести на экран все элементы массива, например, на C, нужно написать:
for(i=0; arr[i]; i++){
printf("%d\n", arr[i])
}
На Ruby это выглядит приятнее:
arr.each{|el| puts el}
А вот как найти все числа массива, которые делятся на 3 без остатка:
rez = [3,4,5,6,7,8,9,11,12,15,17,21,22,25,30].find_all{|el| (el%3).zero?}
puts rez
На экране появятся числа 3, 6, 9, 12, 15, 21, 30 – всё верно.
Увеличить все элементы в два раза:
rez = [3,4,5,6,7,8,9,11,12,15,17,21,22,25,30].map{|el| el*2}
Разделить массив на две части: в одном собрать все элементы больше 12, а в другом – остальные:
rez = [3,4,5,6,7,8,9,11,12,15,17,21,22,25,30].partition{|el| el>12}
В rez[0] – 15, 17, 21, 22, 25, 30; а в rez[1] – 3, 4, 5, 6, 7, 8, 9, 11, 12
Преимущества итераторов перед циклами очевидны: они проходят по каждому элементу единожды. В отличие от циклов у них нет счётчика, который можно подкручивать.
Их много, и каждый делает своё дело.
Индексы
Ну что за программа без массивов? Думаю, таких нет. Так вот, как, например, выбрать из массива три последних элемента?
Не знаю, как это делаете вы, а я – так:
a = [1,2,3,4,5,6,7,8,9,0]
a[-3..-1] # => [8, 9, 0]
Да, отрицательные индексы! Очень удобно.
str = 'String'
str[1] # => 116
str[1].chr # => 't'
Квадратные скобки у строк возвращают коды символов, а не сами символы. Для преобразования кодов в символы используется метод chr. А квадратные скобки у чисел возвращают значения соответствующих битов.
print 5[0], 5[1], 5[2] # => 101
Вывод на экран
Для вывода на экран есть три метода: puts, print и p. У каждого класса имеются методы to_s и inspect (они наследуются от класса Object). Методы puts и print выводят возвращаемое методом to_s значение, разница лишь в том, что puts после вывода очередного аргумента ставит перевод строки, а print нет. Метод p выводит значение метода inspect и используется для отладки. Методы to_s и inspect должны возвращать именно строку.
Метод to_s класса Integer (целые числа) может принимать в качестве аргумента целое число – основание системы счисления.
5.to_s(2) # => '101'
8.to_s(7) # => '11'
59.to_s(27) # => '25'
100.to_s(36) # => '2s'
Следует не забывать, что to_s возвращает строку, т.е. 5.to_s(2)*2 вернёт не 10, и даже не 1010, а '101101'.
Хотелось бы отметить, что Ruby уже во многих школах преподают вместо Basic. Также его преподают и в университетах в целях изучения ООП (даже на специальностях, не связанных с информационными технологиями). Всё это потому, что Ruby – самый лёгкий язык программирования.
Скорость написания программ, их компактность и, что немаловажно, их читаемость поражают воображение. Под читаемостью понимается возможность разобраться в исходном коде другому программисту без комментариев.
Несмотря на сравнительно недавний бум Ruby, для него уже написано огромное количество модулей на все случаи жизни. А благодаря автоматическому сборщику мусора и удобному API крайне легко использовать для нужд Ruby библиотеки, написанные на C.
И напоследок:
Ruby – язык завтрашнего для. Учите, дерзайте и развивайте!
- Скачать Ruby и множество библиотек к нему можно с сайтов – http://www.ruby-lang.org и http://www.rubyforge.com.
- Больше о Ruby можно узнать на http://ru.wikibooks.org/wiki/Ruby и http://ruby-doc.org.
- Programming Ruby. The Pragmatic Programmer's Guide – http://pragmaticprogrammer.com. Русскоязычной литературы пока нет, но издательство «Питер» планирует переводить эту книгу.
- Интересные скринкасты – http://showmedo.com/videos/series?name=rubyRailsOriginalCastsSeries и http://showmedo.com/videos/video?name=rubyGrosenbachDeprec&fromSeriesID=48.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|