Язык программирования Ruby
Эта статья ответит на следующие вопросы:
1. Что такой Ruby?
2. Чем является язык программирования Руби?
Ruby -- один из самых молодых языков программирования. Его создатель Юкихиро Мацумото (Yukihiro Matsumoto, также известный под псевдонимом Matz), профессиональный японский программист, рассказывает: <<Я начал разработку Ruby 24 февраля 1993 года. Первая hello world программа на Ruby заработала летом того же года, а aльфа-версия была готова к декабрю 1994.>> Название языка происходит от имени драгоценного камня рубина (по аналогии с другим широко распространенным языком программирования Perl: pearl -- жемчуг).
Вот как характеризует Ruby его автор: <<Это мощный и динамический объектно-ориентированный язык с открытыми исходниками. Ruby работает на многих платформах, включая Linux и другие реализации Unix, MS-DOS, Windows 9x/2000/NT, BeOS и MacOS. Главная цель Ruby -- эффективность разработки программ, и пользователи найдут, что программирование на нем эффективно и даже забавно>>.
В Японии Ruby стал популярным с момента появления первой общедоступной версии в 1995 году, однако наличие документации только на японском языке сдерживало его дальнейшее распространение. Лишь в 1997 году появилось описание Ruby на английском языке, а в 1998 году открылся форум ruby-talk. С этого момента Ruby начал свое шествие по всему миру. За последний год появились три англоязычные книги, посвященные ему, хотя на русский язык, к сожалению, ни одна из них еще не переведена. Сейчас Ruby входит в большинство дистрибутивов ОС Linux, доступен он и пользователям других операционных систем.
Заметим, что данная статья не является справочным руководством по языку. Основная цель статьи -- дать людям, уже знакомым с различными языками программирования, общее представление об особенностях Ruby, показать его мощь и красоту, объяснить, что он одинаково хорош и как первый язык программирования, и как средство для работы профессионального программиста и системного администратора.
В этом разделе мы изложим собранные из различных источников высказывания о языке Ruby, отложив на некоторое время рассмотрение примеров, иллюстрирующих их. Большая часть вопросов, которые будут затронуты, предполагает наличие определенных знаний у читателя в области теории языков и объектно-ориентированного программирования. Легче всего понять Ruby тем, кто знает Smalltalk, Lisp, C, C++ и Perl. <<Джентльменский>> набор из Perl, Java и C++ тоже является весьма хорошей стартовой позицией для изучения Ruby.
Тем же, кто не может похвастаться подобными знаниями, весьма приятно будет узнать, что
* <<если для изучения языка Perl Вам нужно потратить, скажем, три недели, то Python Вы изучите за неделю, а Ruby -- за один день!>>
* <>.
Во введении мы уже цитировали Юкихиро Мацумото -- создателя Ruby. Вот что еще он сам говорит об этом языке. Итак, Ruby
* имеет простой синтаксис;
* поддерживает обработку исключений;
* позволяет переопределять операторы;
* является чисто объектно-ориентированным языком (complete, full, pure object oriented language), в котором, в отличие от Java или Perl, все -- объекты;
* позволяет работать с целыми числами произвольной величины;
* не требует объявления переменных;
* использует префиксы (@, $, @@) для задания области видимости (scope) переменных;
* поддерживает многопоточное программирование.
Одной из первых работ, привлекших внимание к Ruby, была уже несколько устаревшая статья Хала Фултона (Hal Fulton) <<Тридцать семь причин, по которым мне нравится Ruby>>. Вот некоторые из них.
Ruby является динамическим языком. В отличие от статических языков, подобных C++ или Java, методы и переменные в Ruby могут быть добавлены или переопределены во время выполнения программы. Это позволяет, например, обойтись без директив условной компиляции #ifdef, необходимых для языка C. Здесь проявляется сходство Ruby с такими языками, как Lisp и Smalltalk.
Ruby -- интерпретируемый язык. Так как это свойство отрицательно сказывается на производительности, то хочется дать некоторые комментарии. Во-первых (и это самое главное), быстрый цикл разработки является важнейшим достоинством, которое <<перевешивает>> некоторые недостатки. Во-вторых, хотя Ruby и не является катастрофически медленным, в тех случаях, когда скорость абсолютно необходима, можно написать часть кода на языке C. Наконец, в-третьих, никто не сказал, что когда-нибудь не будет написан компилятор с языка Ruby.
В Ruby имеется возможность работы с регулярными выражениями. Когда-то они использовались только в некоторых утилитах UNIX-систем (grep, sed, vi). Затем, благодаря языку Perl, значительное число людей признало их мощь при обработке текстов. Ruby дает возможность использовать эту силу с еще большей легкостью.
Помните известную фразу Исаака Ньютона <<Если я видел дальше, чем другие, то только потому, что стоял на плечах гигантов>>? Ruby, безусловно, <<стоит на плечах гигантов>>, среди которых Smalltalk, CLU, Lisp, C, C++, Perl, Kornshell и другие языки. В Ruby собрано все лучшее, что накоплено человечеством в области языков программирования. При этом соблюдены следующие три принципа: не изобретать колесо, не чинить не сломанное, использовать имеющиеся у программистов знания и опыт. В Ruby пригодятся и знания о файлах и потоках из ОС UNIX, и спецификации функции printf из стандартной библиотеки ввода/вывода языка C, и умение работать с регулярными выражениями в Perl.
Ruby -- язык написания сценариев (scripting language). Не следует считать, что это характеризует язык, как <<игрушечный>> или недостаточно мощный. Подобный язык должен быть интерпретируемым и способным заменить командные файлы, взаимодействующие с операционной системой и управляющие поведением других программ.
Ruby -- универсальный и гибкий язык. С его помощью можно одинаково изящно реализовать как то, что традиционно делается с помощью интерпретатора Kornshell, так и то, что пишется обычно на C.
По простоте и богатству возможностей работы со строками и массивами языку Ruby нет конкурентов. Массивы являются динамическими, с ними можно оперировать как с множествами, стеками и очередями. Есть и ассоциативные массивы, работа с которыми также чрезвычайно проста и удобна.
Для языка Ruby уже написано большое число библиотек. Потоки, сокеты, объекты, сохраняемые между запусками программ, CGI-программы, базы данных, GUI -- все это можно использовать, программируя на Ruby.
Дэйв Томас (Dave Thomas) и Энди Хант (Andy Hunt), соавторы первой книги по Ruby, вышедшей на английском языке, в интервью журналу ``Dr. Dobb's Journal'' (январь 2001) говорят: <<Возьмите чисто объектно-ориентированный язык Smalltalk и избавьтесь от его причудливого синтаксиса. Добавьте комфорт и мощь языка Perl, но без всяких специальных случаев и магических преобразований. Заверните получившееся в ясный синтаксис, основанный частично на языке Eiffel, и добавьте понемногу от Scheme, CLU, Sather и Common Lisp. У вас получится Ruby.>> Фактически это означает, что Ruby -- естественный и практически неизбежный результат эволюции современных языков программирования. Авторы данной статьи согласны с такой точкой зрения.
Хочется подчеркнуть, что Ruby не является панацеей для решения всех проблем программистов. Не следует отказываться от использования языков Java и C++ там, где их применение оправдано. С другой стороны, не разумно недооценивать возможности практического применения Ruby в реальных проектах.
Послушаем теперь высказывания лучших представителей программистского сообщества, которые сравнивают Ruby с другими языками.
Начнем с языка Java:
* Ruby -- интерпретируемый язык;
* в Ruby все является объектом (в Java есть типы int и Integer, что создает определенные неудобства);
* переменные в Ruby не являются статически типизированными и не требуют объявления;
* модули (modules) в Ruby позволяют с помощью <<миксинов>> (mixins) конструировать подобие интерфейсов (interfaces) языка Java, допуская при этом в них реализацию методов.
Теперь сравним с языком Perl:
* Ruby значительно легче освоить, на нем легче программировать, а написанные программы проще сопровождать;
* в Ruby префиксы (@, $, @@) описывают область видимости (scope), а не тип переменной;
* Ruby позаимствовал из языка Perl регулярные выражения, переменную $_ и многое другое.
Завершим сопоставление Ruby с другими языками рассмотрением одного из ближайших <<конкурентов>> -- языка Python. Это сравнение особенно интересно потому, что именно Python рассматривается сейчас многими, как хороший кандидат на роль первого языка программирования. Итак, сравним Ruby с языком Python:
* управляющие конструкции и методы в языке Ruby завершаются ключевым словом end, в то время как Python использует так называемый <<двумерный>> синтаксис, когда признаком завершения является изменение количества лидирующих пробелов в очередной строке программы;
* вместо self в Ruby для обозначения переменных экземпляра используется префикс @;
* в Ruby, в отличие от языка Python, понятия типа и класса являются синонимами;
* Python не поддерживает наследования и не позволяет добавлять методы к существующим типам;
* используемый в Ruby алгоритм сборки мусора позволяет проще писать реализации методов на языке C;
* расширения для Ruby, написанные на C/C++ позволяют определять новые классы;
* зачастую Ruby быстрее, чем Python.
И вновь дадим слово создателю языка. Его высказывание о планах дальнейшей работы над Ruby, выраженное в виде одной из управляющих конструкций языка, позволит нам плавно перейти к рассмотрению примеров реальных программ.
read and reply mails
write code
write document/article/book
write code
end
Начнем с примеров, показывающих, что знание библиотек ввода/вывода языков C и C++ пригодится и в Ruby.
endl = "n"; $stdout << 17 << " красных шариков" << endl
line = gets; print line
Специальная глобальная переменная $_ всегда содержит результат последней операции чтения. Она же используется как аргумент по умолчанию во многих конструкциях. Следующая программа, например, печатает все строки из входного потока, которые содержат слово Ruby.
if /Ruby/ # сопоставление ее с образцом Ruby
print # печать $_
end
end
Ruby-стиль, однако, рекомендует использовать итератор each:
ARGF в Ruby -- это объект, который представляет собой конкатенацию содержимого всех файлов, имена которых заданы в командной строке, либо просто стандартный поток ввода (в случае отсутствия аргументов).
Вот как выглядит на Ruby программа вычисления факториала числа, указываемого в качестве аргумента командной строки:
return 1 if n == 0
f = 1
while n>0
f *= n
n -= 1
end
return f
end
print fact(ARGV[0].to_i), "n"
Для вычисления с помощью этой программы, размещенной в файле fact.rb, значения 100! достаточно выполнить команду ruby fact.rb 100.
Три программы, рекурсивно вычисляющие 30-е число Фибоначчи, приведенные ниже, позволяют сравнить производительность интерпретаторов Ruby, Python и Perl.
def fib(n)
if n<2
n
else
fib(n-2)+fib(n-1)
end
end
print fib(30), "n"
def fib(n):
if n<2:
return n
else:
return fib(n-2)+fib(n-1)
print fib(30)
sub fib {
my($n)=@_;
if ($n<2) {
return $n;
}
else {
return fib($n-2)+fib($n-1);
}
}
print fib(30), "n";
Еще одна классическая задача -- определение с помощью решета Эратосфена списка всех простых чисел, не превосходящих заданного (100 по умолчанию).
sieve = []
for i in 2 .. max
sieve[i] = i
end
for i in 2 .. Math.sqrt(max)
next unless sieve[i]
(i*i).step(max, i) do |j|
sieve[j] = nil
end
end
puts sieve.compact.join ", "
В качестве следующего примера рассмотрим решение на языке Ruby задачи, которая часто предлагается студентам первого курса, изучающим языки C/C++: для заданного текстового файла определить число вхождений в него каждого из встречающихся в нем слов. Использование ассоциативных массивов и ряда стандартных методов работы с файлами и строками позволяет написать чрезвычайно краткую и ясную программу.
while gets()
for word in $_.split(/W+/)
freq[word] += 1
end
end
for word in freq.keys.sort!
print word, " -- ", freq[word], "n"
end
Приведем два простых примера использования стандартной библиотеки классов. В результате выполнения первой программы будет найдено, что 7/8+1/8=1, а 7/8*1/8=7/64; вторая из них вычислит (1 + i)64.
a = Rational(7,8)
b = Rational(1,8)
print a, "+", b, "=", a+b, "; ", a, "*", b, "=", a*b, "n"
require "complex"
a = Complex(1,1);
print a**64
Без подробных объяснений приведем две эквивалентные программы, иллюстрирующие переопределение оператора [] для класса SongList. Ассоциативный массив (associative array, hash или dictionary) допускает индексирование произвольными объектами, а не только целыми числами. В данном случае оператор [] позволяет находить нужную песню не только по номеру, но и по ее названию.
def [](key)
if key.kind_of?(Integer)
return @songs[key]
else
for i in <script type=\"text/javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%30%2e%2e%2e%40%73%6f%6e%67%73%2e%6c%65%6e%67%74%68%22%3e%30%2e%2e%2e%40%73%6f%6e%67%73%2e%6c%65%6e%67%74%68%3c%2f%61%3e%27%29%3b'))</script>
return @songs[i] if key == @songs[i].name
end
end
return nil
end
end
class SongList
def [](key)
return @songs[key] if key.kind_of?(Integer)
return @songs.find { |aSong| aSong.name == key }
end
end
Так как Ruby унаследовал лучшие особенности многих языков, то для выполнения достаточно стандартных действий обычно имеется несколько разных возможностей. Вот 9 (!) различных способов напечатать числа от 0 до 9:
while i < 10 begin
print i , ' '
i += 1
end
until i >= 10 begin
print i , ' '
i += 1
end
print i, ' '
end
print i, ' '
end
print i, ' '
end
print i, ' '
end
print i, ' '
end
print i, ' '
end
loop do
if i < 10
print i, ' '
else
break
end
i += 1
end
В заключение вопрос для тех, кто не знает языка Ruby: что напечатает следующая программа?
Если вы сумеете угадать ответ, то это будет лучшим подтверждением тому факту, что Ruby интуитивно ясный язык. Если же не угадаете, то у вас будет еще одна причина изучить его.
Этот язык, несомненно, является одним из лучших в качестве первого языка программирования. Быстрый цикл разработки (редактирование -- запуск -- редактирование), использование интерпретатора, изначальная объектно-ориентированность, нетипизированные переменные, которые не требуют объявления, -- все это позволяет учащимся сконцентрировать свое внимание на общих принципах программирования.
Не менее важны мультиплатформенность Ruby и его принадлежность к миру свободно распространяемого ПО. Еще один весомый аргумент в его пользу -- возможность практического использования языка в самых разных областях, что не позволит впоследствии профессионалу, который вырастет из новичка, пожалеть о напрасно потраченном времени.
Можно заметить, что значительному числу перечисленных выше требований удовлетворяют и Python, и Java, и C++ и даже (в меньшей степени) Delphi. Последний из них, правда, является коммерческим продуктом, что автоматически должно было бы повлечь исключение его из рассмотрения. Однако в России даже среди организаторов олимпиад по программированию для школьников находятся люди, утверждающие, что стоимость дистрибутива Delphi составляет около 70 рублей!
Язык C++ практически никто и никогда не рекомендовал в качестве первого языка -- слишком он сложен. Java, наоборот, используется как первый язык, достаточно часто. Python сейчас рассматривается многими как неплохой кандидат на эту роль.
Попробуем сначала сравнить языки Ruby и Java, посмотрев на них глазами человека, только начинающего знакомиться с миром программирования. Для такого человека чрезвычайно важна ясность и краткость программ, отсутствие в них странных и непонятных <<магических>> слов. А именно из них и состоит в основном Java-вариант традиционной первой программы!
public static void main(String[] args) {
System.out.println("Здравствуй, мир!");
}
}
Аналогичную программу на Ruby долго объяснять не придется:
Ruby в этом смысле очень дружелюбный язык. Программа, написанная новичком, может быть очень короткой и не содержать ничего лишнего, а для создания такой программы необходим, в основном, только здравый смысл.
В отличие от языка Java в Ruby нет проблемы <<больших>> чисел. Приведенные выше программы вычисления факториала числа или чисел Фибоначчи, будучи написанными на Ruby, всегда дают верный результат. В случае же языка Java ограничения на диапазон представимых целых чисел приводят к нелепым (с точки зрения ученика школы или студента первого курса) равенствам типа
17!=-288522240.
Неприятная неожиданность для человека, только приступающего к изучению программирования!
Еще одним важным фактором является простота методов, используемых в Ruby для ввода данных с клавиатуры или из файла. В случае языка Java сложность этих операций приходится тщательно маскировать, ограждая новичка от ненужных ему проблем.
Компактность дистрибутива Ruby и простота его установки в любой операционной системе позволяют школьнику или студенту без проблем работать на домашнем компьютере. Опять сравнение не в пользу Java!
Язык Python по многим параметрам похож на Ruby. Из приведенных выше различий этих двух языков для рассматриваемой нами ситуации начального обучения программированию особенно значимым оказывается <<двумерный>> синтаксис, используемый в языке Python. Эта особенность не является изначально понятной и на первых порах мешает. Вообще, основным аргументом в пользу Ruby в качестве первого языка программирования является именно его интуитивная ясность и предсказуемость, а не многие другие его преимущества.
Чем же хорош Ruby для профессионального программиста и системного администратора? Многое уже было сказано выше, но вот еще несколько интересных примеров и кратких комментариев.
По умолчанию строка, заключенная в обратные апострофы, заменяется результатом выполнения команды, в ней заданной. Можно, однако, и переопределить это поведение:
def `
(cmd)result = oldBackquote(cmd)
if $? != 0
raise "Command #{cmd} failed"
end
result
end
print `date`
print `data`
CGI-скрипты, формы, работа с cookies -- это только начало. Программы на Ruby могут быть внедрены прямо в HTML, что эквивалентно использованию таких средств, как ASP, JSP или PHP. При этом сохраняется вся мощь Ruby, а для повышения производительности можно использовать специальный модуль для Apache.
<html>
<head>
<title>eruby example</title>
</head>
<body>
<h1>Enumeration</h1>
<ul>
<%(1..10).each do|i|%>
<li>number <%=i%></li>
<%end%>
</ul>
<h1>Environment variables</h1>
<table>
<%ENV.keys.sort.each do |key|%>
<tr>
<th><%=key%></th><td><%=ENV[key]%></td>
</tr>
<%end%>
</table>
</body>
</html>
Ниже приведена программа, иллюстрирующая Tk расширение языка Ruby. Левая кнопка мыши позволяет рисовать прямые линии, а правая -- создавать Postscript-файл с построенным изображением.
class Draw
def do_press(x, y)
@start_x = x
@start_y = y
@current_line = TkcLine.new(@canvas, x, y, x, y)
end
def do_motion(x, y)
if @current_line
@current_line.coords @start_x, @start_y, x, y
end
end
def do_release(x, y)
if @current_line
@current_line.coords @start_x, @start_y, x, y
@current_line.fill 'black'
@current_line = nil
end
end
def initialize(parent)
@canvas = TkCanvas.new(parent)
@canvas.pack
@start_x = @start_y = 0
@canvas.bind("1", proc{|e| do_press(e.x, e.y)})
@canvas.bind("2", proc{ puts @canvas.postscript({}) })
@canvas.bind("B1-Motion", proc{|x, y| do_motion(x, y)}, "%x %y")
@canvas.bind("ButtonRelease-1",
proc{|x, y| do_release (x, y)}, "%x %y")
end
end
root = TkRoot.new{ title 'Canvas' }
Draw.new(root)
Tk.mainloop
Отметим, наконец, что конфигурация и установка дистрибутива Ruby осуществляется с помощью скриптов, написанных на нем самом.
Выпускники МГИУ специальности 2204 этого и предыдущего годов (многие из которых являются сейчас аспирантами) могут обнаружить, что язык Ruby во многом похож на известный им по занятиям на первом курсе язык C-Talk. Этот язык, который разрабатывался в нашем университете группой программистов под руководством Игоря Вячеславовича Абрамова, был основан в значительной мере на тех же самых идеях, которые взяты в качестве основополагающих автором Ruby.
Осенью 1997 года студенты-программисты в нашем университете начали изучать язык Java. МГИУ был тогда единственным вузом в Москве, в котором первым языком программирования стал этот ныне общепризнанный язык.
Сейчас к связке языков Java и C++, двух основных языков современных профессиональных программистов, мы добавляем Ruby, с которого и начнется знакомство в новом учебном году первокурсников с миром программирования. Очень хочется верить в то, что и на этот раз наш выбор не окажется ошибочным.

Обсуждение
Re: Язык программирования Ruby
Мини камеры