Loading AI tools
интерпретируемый язык программирования Из Википедии, свободной энциклопедии
Ruby (англ. ruby — рубин, произносится ['ru:bɪ] — ру́би) — динамический, рефлективный, интерпретируемый высокоуровневый язык программирования[9][10]. Язык обладает независимой от операционной системы реализацией многопоточности, сильной динамической типизацией, сборщиком мусора и многими другими возможностями . По особенностям синтаксиса он близок к языкам Perl и Eiffel, по объектно-ориентированному подходу — к Smalltalk. Также некоторые черты языка взяты из Python, Lisp, Dylan и Клу.
Ruby | |
---|---|
![]() | |
Класс языка | объектно-ориентированный |
Появился в | 1995[1] |
Автор | Юкихиро Мацумото |
Расширение файлов |
.rb или .rbw |
Выпуск | |
Система типов | строгая, динамическая (утиная) |
Основные реализации | Ruby MRI[англ.], JRuby, Rubinius |
Испытал влияние | Ада, Dylan, Perl[3], Python[3], Smalltalk, C++, Клу, Eiffel, Лисп, Бейсик, Lua и Emacs[4] |
Повлиял на | Raku, Groovy, Crystal[5] |
Лицензия | Лицензия Ruby[вд], GNU GPL 2[6] и 2-пунктная лицензия BSD[вд][7] |
Сайт | ruby-lang.org (англ.) |
ОС | Windows[8], Linux, BSD[вд][8] и macOS[8] |
![]() |
Кроссплатформенная реализация интерпретатора языка является полностью свободной[11].
Создатель Ruby — Юкихиро Мацумото (Matz) — интересовался языками программирования, ещё будучи студентом, но идея о разработке нового языка появилась позже. Ruby начал разрабатываться 23 февраля 1993 года и вышел в свет в 1995 году.
Название навеяно языком Perl, многие особенности синтаксиса и семантики из которого заимствованы в Ruby: англ. pearl — «жемчужина», ruby — «рубин».
Одним из источников вдохновения для Мацумото для разработки Ruby был научно-фантастический роман «Вавилон-17», основанный на гипотезе Сепира — Уорфа[12].
Целью разработки было создание «настоящего объектно-ориентированного», лёгкого в разработке, интерпретируемого языка программирования. Из письма автора[13]:
Ruby родился 24 февраля 1993 года. В тот день я беседовал со своим коллегой о возможности существования объектно-ориентированного сценарного языка. Я знал Perl (Perl4, а не Perl5), но он мне не нравился — был в нём некий привкус игрушечного языка (да и поныне есть). А объектно-ориентированный интерпретируемый язык казался многообещающим. В то время я знал Python. Но он мне не нравился потому, что я не считал его настоящим объектно-ориентированным языком. Его OO-свойства казались надстройкой над языком. Мне, как языковому маньяку и фанату объектно-ориентированного программирования с пятнадцатилетним стажем, очень, очень хотелось, чтобы был истинно объектно-ориентированный, простой в использовании язык. Я пытался найти такой язык, но его не было.
Тогда я решил его создать. Прошло несколько месяцев, прежде чем интерпретатор заработал. Я добавил в свой язык то, что мне хотелось — итераторы, обработку исключений, автоматическую сборку мусора. Затем я переорганизовал свойства Perl и реализовал их как библиотеку классов. В декабре 1995 года я опубликовал Ruby 0.95 в японских новостных группах. С тех пор появились сайты, списки рассылок. В списках рассылок идут жаркие обсуждения. Самый старый список сейчас содержит 14 789 писем.
В Японии Ruby стал популярным с момента появления первой общедоступной версии в 1995 году, однако наличие документации только на японском языке сдерживало его дальнейшее распространение. Лишь в 1997 году появилось описание Ruby на английском языке, а в 1998 году открылся форум «ruby-talk». Это положило начало росту известности языка в остальном мире. В начале 2000-х вышло несколько книг на английском языке, что способствовало росту популярности Ruby в Западной Европе и Америке. В 2003 году была выпущена версия Ruby 1.8.0, а в 2005 году появился веб-фреймворк Ruby on Rails, написанный на Ruby и сразу завоевавший признание благодаря лёгкости построения на нём типичных веб-приложений. Ruby в нём является не только языком реализации самого фреймворка, но и языком описания решений (в частности, используются HTML-шаблоны с встроенным кодом на Ruby).
Основной проблемой как для Ruby вообще, так и для Ruby on Rails на тот момент была производительность: оригинальный интерпретатор проигрывал в скорости как языкам-конкурентам, так и альтернативным реализациям, а масштабируемость приложений ограничивалась высокими потребностями в памяти. Разработка языка во второй половине 2000-х разделилась на две ветви: одновременно с поддержкой линии 1.8.* началась разработка экспериментальной ветви 1.9.*, в которой автор языка отошёл от принципов сохранения совместимости с предыдущими версиями и внёс значительные изменения, подготовительные к выпуску Ruby 2.0. В результате с выходом версии Ruby 1.9.1 в 2009 и Rails 3.0 в 2010 году положение существенно изменилось: скорость работы оригинального интерпретатора была увеличена в несколько раз и практически сравнялась с альтернативными реализациями под .NET и JVM, модификации языка устранили некоторые часто критикуемые моменты. Согласно рейтингу TIOBE и данным indeed.com, интерес к Ruby за период с 2009 по 2012 год вырос более чем в три раза. В России первые официальные издания русских переводов книг по Ruby появились в 2011 году и с этого времени выходят регулярно, что можно расценивать как свидетельство растущего интереса к языку у русскоговорящих специалистов.
Стабильная версия Ruby 2.0 вышла в феврале 2013 года. 24 февраля 2014 года исполнился 21 год с момента анонса языка программирования Ruby. Такое событие разработчики решили отметить выпуском патча для Ruby 2.1, который назвали Ruby 2.1.1[14]. В конце 2018 года вышел Ruby 2.6, где реализована JIT-компиляция.
Сейчас[когда?] Ruby входит в большинство дистрибутивов Linux, поставляется вместе с Mac OS X, доступен пользователям других операционных систем. Одним из основных приложений, связанных с Ruby, продолжает оставаться Ruby on Rails, который продолжает активно развиваться, но использование Ruby значительно шире — на нём разрабатывается большое количество приложений различного назначения, кроме того, он используется в качестве скриптового языка для автоматизации и настройки приложений и написания административных утилит, в частности, в ОС Linux.
Мацумото, фанат объектно-ориентированного программирования, мечтал о языке, более мощном, чем Perl, и более объектно-ориентированном, чем Python. Основное назначение Ruby — создание простых и в то же время понятных программ для решения задач, в которых время разработки, понятность и простота важнее, чем скорость работы.
Принципы устройства Ruby и программирования на нём иногда выделяются в термин «Путь Ruby» (англ. Ruby Way). В целом «путь Ruby» не имеет точной формулировки, иногда этот термин используется для критики.[15] В относительно сжатом виде его положения изложены в книгах «Программирование на языке Ruby» Хэла Фултона[16] и «Путь Ruby» Хэла Фултона и Андре Арке[17].
Ruby — полностью объектно-ориентированный язык. В нём все данные являются объектами, в отличие от многих других языков, где существуют примитивные типы. Каждая функция — метод.
Любая конструкция в Ruby возвращает значение. Например:
# Условный оператор возвращает значение выбранной ветви
puts( if 5 > 3 then "Одно" else "Другое" end ) #=> Одно
# Операция присваивания возвращает присвоенное значение
puts( var = 5 ) #=> 5
Ruby использует вызов по соиспользованию (call-by-sharing), хотя в сообществе Ruby часто говорят, что он использует вызов по ссылке. Для программиста, привыкшего к распространённым гибридным языкам программирования, некоторые эффекты такого решения могут показаться неожиданными. Например:
a = "abcdefg" # => "abcdefg" - переменная a инициализирована новой строкой.
b = a # => "abcdefg" - переменная b получает ссылку на ТУ ЖЕ строку.
a[3] = 'R' # => "abcRefg" - строка, присвоенная a, изменяется.
b # => "abcRefg" - при изменении a неявно изменилось и b, так как они ссылаются на ОДИН объект.
# Однако:
x = 10 # => 10 - переменная x инициализирована числом 10.
y = x # => 10 - переменная y получает ссылку на то же значение.
x += 5 # => 15 - операция += создаёт НОВОЕ целое значение 15, которое и записывается в x,
y # => 10 поэтому изменение x не отражается на y
Механизм присваивания действует одинаково для всех объектов, в отличие от языков типа Object Pascal, где присваивание может означать как копирование значения, так и копирование ссылки на значение.
Ruby не поддерживает множественное наследование, но вместо него есть мощный механизм примесей. Все классы (напрямую или через другие классы) выведены из класса Object
, следовательно, любой объект может использовать определённые в нём методы (например, class
, to_s
, nil?
). Процедурный стиль также поддерживается, но все глобальные процедуры неявно являются закрытыми методами класса Object
.
Ruby является мультипарадигменным языком: он поддерживает процедурный стиль (определение функций и переменных вне классов), объектно-ориентированный (всё — объект), функциональный (анонимные функции, замыкания, возврат значения всеми инструкциями, возврат функцией последнего вычисленного значения). Он поддерживает рефлексию, метапрограммирование, информацию о типах переменных на стадии выполнения (см. динамическая идентификация типа данных).
Integer
. Единственное исключение — управляющие конструкции, которые в Ruby, в отличие от Smalltalk, не являются объектами. Также поддерживается добавление методов в класс и даже в конкретный экземпляр во время выполнения программы.{
… }
или do
… end
). Блоки могут использоваться в методах или преобразовываться в замыкания.Fixnum
(32-разрядные) и Bignum
(больше 32 разрядов) в зависимости от их значения, что позволяет производить целочисленные математические расчёты со сколь угодно большой точностью.Строчные комментарии начинаются с символа #
. Также поддерживаются многострочные комментарии:
x = 10 # Строчный комментарий начинается со знака # и продолжается до конца текущей строки
=begin
Всё, что находится между =begin и =end, является комментарием.
Ограничители такого комментария обязательно должны быть записаны с начала строки.
=end
Ruby — регистро-зависимый язык, прописные и строчные буквы в идентификаторах являются различными. Все ключевые слова языка, за двумя исключениями, пишутся в нижнем регистре.
До версии 2.0 язык использовал множество символов 7-битной кодировки ASCII. Начиная с версии 2.0 поддерживается Unicode, по умолчанию файлы исходного кода используют кодировку UTF-8. Все буквенные символы Unicode допускается использовать в идентификаторах наравне с английскими буквами. Полностью поддерживаются Unicode-строки.
Список ключевых слов Ruby:
alias and BEGIN begin break case class def
defined? do else elsif END end ensure false
for if in module next nil not or
redo rescue retry return self super then true
undef unless until when while yield
Идентификаторы традиционно должны состоять из букв, цифр и знаков подчёркивания и начинаться с буквы или знака подчёркивания. Ruby использует соглашение об именовании:
Также используются префиксы имён, определяющие область видимости идентификатора:
Для имён методов применяются суффиксы, обозначающие назначение метода:
Ruby реализует идеологию «всё — объект», то есть любая единица данных является объектом — экземпляром некоторого класса, к которому применимы все синтаксические средства, предназначенные для работы с объектами. В этом смысле язык не содержит встроенных примитивных типов данных. Условно таковыми можно считать типы, предоставляемые интерпретатором и системной библиотекой, используемые наиболее часто и не требующие для использования специального указания имени класса.
![]() | Информация в этой статье или некоторых её разделах устарела. |
Fixnum
и Bignum
. Первый тип используется для чисел, по модулю не превышающих 230, второй — для чисел более 230. В арифметических операциях эти числовые типы полностью совместимы и могут свободно использоваться вместе, между ними обеспечивается прозрачная конвертация. Тип Fixnum
имеет ограниченную разрядность и использует стандартные арифметические команды процессора; разрядность Bignum
ограничена только объёмом доступной оперативной памяти, а операции с ними базируются на алгоритмах вычислений с неограниченной точностью. Это позволяет производить точные вычисления с любым требуемым количеством знаков. Например, для большинства языков программирования написать программу точного вычисления факториала, которая работала бы для аргумента порядка сотни — достаточно сложная задача. В Ruby это делается элементарно, так как проблемы работы с длинными числами берёт на себя интерпретатор.def fact (n)
result = 1
for i in 1..n do
result *= i
end
result
end
puts fact(100)
=begin
Выведет:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
=end
Float
— числа с плавающей запятой, представленные фиксированным числом разрядов. Плавающие числа записываются либо в естественной, либо в экспоненциальной форме. Системная библиотека mathn предоставляет также типы Rational
(рациональное число) и Complex
(комплексное число). Оба этих типа автоматически преобразуются к целым и плавающим при единичном знаменателе и нулевой мнимой части соответственно.%q[…]
или %Q[…]
(можно использовать круглые, квадратные, фигурные и угловые скобки) позволяют записывать строки с использованием апострофов и кавычек без экранирования. Форма %q[…]
также обеспечивает непосредственный вывод управляющих последовательностей: # Будет выведено три одинаковых строки:
puts %q[Строка с табуляцией "\t" и символом переноса '\n']
puts "Строка с табуляцией \"\\t\" и символом переноса '\\n'"
puts 'Строка с табуляцией "\t" и символом переноса \'\n\''
puts <<EOF
В этом тексте
всё, включая переводы строк,
кавычки и отступы,
будет выведено "как есть".
EOF
#{ }
, то всё, что находится внутри фигурных скобок, вычисляется интерпретатором, преобразуется в строковый формат и помещается в данное место создаваемой строки. for i in (1..7).reverse_each do
puts "Осталось #{i} секунд#{case i
when 2..4 then "ы"
when 1 then "а"
else ""
end }..."
sleep(1)
end
puts "Готово!"
=begin
Выведет:
Осталось 7 секунд...
Осталось 6 секунд...
Осталось 5 секунд...
Осталось 4 секунды...
Осталось 3 секунды...
Осталось 2 секунды...
Осталось 1 секунда...
Готово!
=end
:
» (двоеточие). sym = :monday # :monday — это символ
puts sym # ==> monday
puts :sunday # ==> sunday
und = :"Unknown\tday of week" # Символ в кавычках может содержать пробелы и спецсимволы
# для символов работает получение срезов
puts und[8,6] # ==> day of
und[7] = ' ' # ОШИБКА! Символы неизменяемы.
d1 = 1..10 # Две точки - от 1 до 10 включительно.
d2 = 1...10 # Три точки - от 1 до 9. Верхняя граница в такой диапазон не входит!
Диапазоны широко используются в Ruby для выборки данных и организации циклов.
Программа на Ruby представляет собой текстовый файл, содержащий последовательность инструкций — команд и описаний. При запуске программного файла на исполнение интерпретатор последовательно читает файл и выполняет инструкции. В Ruby не требуется организовывать тело главной программы в виде специального программного модуля (подобно функции main()
в языке Си), составляющие его команды просто записываются непосредственно в тексте файла программы. Поскольку программный файл обрабатывается интерпретатором последовательно, любые функции, методы, описания должны предшествовать в тексте программы их первому использованию.
Программа может быть разделена на несколько файлов. В этом случае главный файл программы должен загрузить остальные файлы с помощью инструкции require
или require_relative
:
require 'module1' # загрузка программного файла с именем 'module1.rb' либо библиотеки с именем 'module1'
require 'pkgs/package2' # загрузка программного файла 'package2' из подкаталога pkgs
По данной инструкции происходит поиск файла с указанным именем и расширением '.rb' и его загрузка. Если файла исходного кода с таким именем нет, интерпретатор пытается загрузить динамическую библиотеку с тем же именем (расширения зависят от операционной системы). Пути поиска файлов определяются инструкцией загрузки: require
использует для загрузки набор каталогов, заданных настройками среды и параметрами запуска интерпретатора, а require_relative
загружает файл с указанным путём относительно текущего файла (то есть в примере выше, если файл, содержащий инструкции загрузки, находится в каталоге /home/programmer/work/ruby/testproject
, то файл package2.rb
будет загружаться из /home/programmer/work/ruby/testproject/pkgs
. При загрузке программный модуль обрабатывается интерпретатором, то есть выполняются все его инструкции. Если модуль загружается в нескольких файлах, то его загрузка происходит только один раз. В Ruby имеется метод load
, также выполняющий загрузку файла исходного кода либо библиотеки, он несколько отличается функциональностью и обычно применяется для загрузки бинарных модулей, написанных на Си.
Ruby содержит богатый набор управляющих конструкций; многие их варианты являются достаточно редкими.
Условный оператор if
выглядит традиционно:
if x > 0 then
puts "x - положительное число"
elsif x < 0 then
puts "x - отрицательное число"
else
puts "x - нуль"
end
Ветвей elsif
может быть любое количество, использование ключевого слова then
допустимо, но не обязательно, ветви elsif
и else
могут отсутствовать. Помимо этой «канонической» формы условного оператора, язык поддерживает и несколько других:
# Условие "если-не"
unless x > 3 then
puts x.to_s # выведет значение x, если оно НЕ больше трёх.
else
puts "очень много, не сосчитать"
end
Можно использовать сокращённые формы условного оператора как модификаторы инструкций. Они пишутся после инструкции и интерпретируются как условие, при котором данную инструкцию следует выполнять. Ветви else
в модификаторах быть не может.
puts "x меньше нуля!" if x < 0 # Печать произойдёт только при отрицательном x
puts "x положительно!" unless x <= 0 # Строка будет выведена, если x БОЛЬШЕ нуля
Можно использовать условный оператор как выражение. Значением его будет значение той ветви, которая была выбрана согласно условию. При таком использовании ключевое слово then обязательно. Также Ruby унаследовал из Си трёхместный условный оператор ?:
.
# Аргумент метода puts выбирается условным выражением.
puts ( if x == 0 then "нуль" else "не нуль" end )
# Аналог предыдущей инструкции, записанный с помощью трёхместного условного оператора.
puts (x == 0)? "нуль" : "не нуль"
Оператор множественного выбора case-when
обеспечивает выбор из нескольких альтернатив, каждая из которых может задаваться отдельным значением, набором значений или диапазоном:
case month
when 1,2,12 then puts "зима" # выбор из списка вариантов
when 3..5 then puts "весна" # выбор из диапазона вариантов
when 6..8 then puts "лето" # можно заменять then на двоеточие
when 9..11 # можно опускать then, если есть перевод строки
puts "осень"
else puts "так не бывает!!!"
end
Альтернативы в операторе case
проверяются последовательно, выбирается первая ветвь, для которой условие соответствует списку значений или диапазону. Если ни одна из ветвей when не выбрана, выполнится ветвь else, если она существует.
В Ruby семь видов циклических конструкций. В примере показаны варианты цикла для обхода массива list
и вывода на печать всех его значений.
# Цикл while ("пока") с предусловием
i=0
while i < list.size do
print "#{ list [i]} "
i += 1
end
# Цикл until ("пока не") с предусловием
i=0
until i == list.size do
print "#{list[i]} "
i += 1
end
# Цикл while с проверкой в конце
i = 0
begin
print "#{list [i]} "
i += 1
end while i < list.size
# Цикл until с проверкой в конце
i = 0
begin
print "#{list[i]} "
i += 1
end until i == list.size
# Цикл for со счётчиком (i обходит заданный диапазон)
for i in 0 .. list.size-1 do
print "#{list[i]} "
end
# Цикл for по коллекции
for х in list do # x принимает значения элементов list
print "#{х} "
end
# Бесконечный цикл loop
i = 0
n = list.size-1
loop do
print "#{list[i]} "
i += 1
break if i > n # Выход при условии
end
# Цикл loop
i = 0
n = list. size-1
loop do
print "#{list[i]} "
i += 1
break unless i <= n # Выход при нарушении условия
end
Ruby поддерживает динамические гетерогенные массивы, которые автоматически изменяют размер и могут содержать элементы любых типов. Массив является экземпляром класса Array, который предоставляет мощные средства для работы с хранимыми данными.
# Массив можно инициализировать списком значений в квадратных скобках.
a = [1, 'hi', 3.14, 1, 2, [4, 5] * 3]
a[2] # Обращение по индексу
# «разворачиваем» все внутренние массивы, удаляем одинаковые элементы
a.flatten.uniq # => [1, 'hi', 3.14, 2, 4, 5]
# поиск элемента по значению
a.index(6) # неудача: возвращается значение nil
a.index(4) # => 5
# почти для всех функций предоставляется
# аналог с тем же названием, но заканчивающийся на «!»,
# который модифицирует сам контейнер
a.flatten! # => [1, "hi", 3.14, 1, 2, 4, 5, 4, 5, 4, 5]
Для контейнерных типов предоставляются итераторы, обеспечивающие обход их элементов.
# Итератор 'each' - по элементам коллекции
list.each do |x|
print "#{х} "
end
# Итератор 'times' - по количеству элементов коллекции
n = list.size
n.times do |i|
print "#{list[i]} "
end
# Итератор 'upto' - от исходного числа до максимального
n = list.size-1
O.upto(n) do |i|
print "#{list[i]} "
end
# Итератор 'each_index'
list.each_index do |x|
print "#{list[x]} "
end
Все классы являются потомками предопределённого класса Object
. Методы класса описываются внутри описания самого класса. Переменные с префиксом @@, встретившиеся в описании класса, являются переменными класса (аналог статических членов класса в C++), переменные с префиксом @ — переменными экземпляра (полями класса).
class Person < Object # класс Person наследуется от Object
include Comparable # подмешивание методов экземпляра из модуля Comparable
@variable # переменная экземпляра
@@count_obj = 0 # переменная класса для подсчёта числа созданных объектов
#
def initialize(name, age) # конструктор (name, age - параметры метода)
@name, @age = name, age # создаём объекты
@@count_obj += 1 # увеличиваем счётчик на 1
end
def <=>(person) # переопределение оператора <=>
@age <=> person.age # из метода возвращается последнее вычисленное выражение
end
def to_s # для форматированного вывода информации puts
"#{@name} (#{@age})" # конструкция #{x} в 2-х кавычках замещается в строке текстовым значением x
end
def inspect # метод используется интерпретатором для диагностического вывода
"<#{@@count_obj}:#{to_s}>"
end
attr_reader :name, :age # создание методов доступа на чтение для полей
end
# Создание массива экземпляров класса Person
group = [ Person.new("John", 20),
Person.new("Markus", 63),
Person.new("Ash", 16) ]
# для вывода автоматически вызывается метод inspect
# => [<3:John (20)>, <3:Markus (63)>, <3:Ash (16)>]
# сортировка и "переворачивание" массива стандартными методами
# работает благодаря переопределению оператора <=>
puts group.sort.reverse # Печатает:
# Markus (63)
# John (20)
# Ash (16)
# метод between добавлен неявно при подключении Comparable
group[0].between?(group[2], group[1]) # => true
Один класс в Ruby может быть объявлен в нескольких файлах исходного кода. В результате возможно, например, добавление новых методов в уже существующий класс.
Ruby поддерживает только единичное наследование. Дополнительно имеется механизм примесей (mixin) и возможность объявления модулей, которые позволяют реализовать большинство возможностей множественного наследования.
В Ruby есть немало оригинальных решений, редко или вообще не встречающихся в распространённых языках программирования. Можно добавлять методы не только в любые классы, но и в любые объекты. Например, вы можете добавить к некоторой строке произвольный метод.
# всё от символа # и до конца строки - комментарий
# = является оператором присваивания,
# символы в «"» - строка, которой можно манипулировать средствами языка
str = "Привет" # здесь создаётся переменная str, типа String
# def - ключевое слово для объявления функции
def str.bye # str. указывает, кому принадлежит метод (по умолчанию Object)
# bye - имя метода, за ним может следовать необязательный, заключённый в
# круглые скобки список параметров функции
"Пока!" # из метода возвращается последнее вычисленное значение (здесь - строка)
end # ключевым словом end заканчиваются практически все инструкции Ruby
# puts - метод,
# str.bye - обращение к методу bye объекта str
# значение, полученное из метода bye, передаётся методу puts,
# который выводит на экран информацию
puts str.bye #=> Пока!
Этот пример также демонстрирует, как в Ruby можно использовать синглтон.
В этом примере синглтоном является объект str
.
В языке есть 2 эквивалентных способа записи блоков кода:
{ puts "Hello, World!" }
do puts "Hello, World!" end
Сопрограммы применяются с большинством встроенных методов:
File.open('file.txt', 'w') {|file| # открытие файла «file.txt» для записи («w» - write)
file.puts 'Wrote some text.'
} # Конструкция устраняет неопределённость с закрытием файла: закрывается здесь при любом исходе
Следующий пример показывает использование сопрограмм и итераторов для работы с массивами, который показывает краткость записи на Ruby многих достаточно сложных действий (случайно выбираем из последовательности квадратов чисел от «0» до «10» и распечатываем вместе с индексами):
# Для работы требуется Ruby 1.9
(0..10).collect{ |v| v ** 2 }.select{ rand(2).zero? }.map.with_index { |*v| v }
Исключения возбуждаются с помощью конструкции raise
(или fail
), опционально могут быть добавлены текст с сообщением, тип исключения и информация о стеке вызовов:
raise ArgumentError, "Неверный аргумент", caller # caller - метод, возвращающий текущий стек выполнения
Обрабатываются исключения с использованием конструкции rescue
. Опционально можно указать тип обрабатываемого исключения (по умолчанию обрабатываются все) и получение информации. Также можно добавлять блоки else
(выполняется, если исключения отсутствовали) и ensure
(выполняется в любом случае).
begin
# ...
rescue RuntimeError => e
# обрабатываем конкретный тип ошибок
puts e # напечатаем сообщение об ошибке
rescue
# можно писать rescue => e, чтобы получить объект исключения
# обрабатываем все исключения
else
# сработает, если исключений не было
ensure
# сработает в любом случае
end
Для Ruby существуют несколько реализаций: официальный интерпретатор, написанный на Си, JRuby — реализация для Java, интерпретатор для платформы .NET IronRuby, Rubinius — написанная в основном на Ruby и базирующаяся на идеях Smalltalk-80 VM[19], MagLev — другая базирующаяся на Smalltalk разработка от компании Gemstone[20], Blue Ruby — реализация Ruby для виртуальной машины ABAP[21], MacRuby — реализация для Mac OS с фокусом на максимальную интеграцию с возможностями операционной системы[22], mruby — реализация для встраивания в программы[23].
Официальный интерпретатор портирован под большинство платформ, включая Unix, Microsoft Windows (в том числе Windows CE), DOS, Mac OS X, OS/2, Amiga, BeOS, Syllable, Acorn RISC OS и другие. Для Windows существует специализированный установщик RubyInstaller и есть возможность запуска под Cygwin для большей совместимости с Unix[24].
С официальной версией интерпретатора Ruby поставляется командная оболочка Ruby (Interactive Ruby Shell). Запускаемая командой irb
в окне терминала (интерфейсе командной строки), она позволяет тестировать код программы очень быстро (построчно):
$ irb
irb(main):001:0> "Hello, World"
=> "Hello, World"
irb(main):002:0> 2 ** 256 # ** - оператор возведения в степень
=> 115792089237316195423570985008687907853269984665640564039457584007913129639936
Программа irb
выводит результат каждой строки после символов =>
. В приведённых выше примерах для наглядности применяется аннотирование — результаты строк программы записываются в комментариях после =>
.
Имитацию irb
можно запустить непосредственно в браузере.
В поставке дистрибутива One-Click Installer для Windows, начиная с версии 1.8.2-15, поставляется утилита fxri
, которая включает в себя справочную систему (ri
) и интерактивный интерпретатор (irb
).
Базовые возможности редактирования добавляются ко многим редакторам (Emacs, Bred, vim, jEdit, nano, SciTE, Kate и др.), здесь перечислены только IDE, предоставляющие обширный набор функций.
Название | Лицензия | Платформы | Ссылка |
---|---|---|---|
ActiveState Komodo IDE | Проприетарная | Linux, Mac OS X, Solaris, Windows | |
Arachno Ruby IDE | Проприетарная | Win 2000/XP, Linux | Архивная копия от 25 декабря 2019 на Wayback Machine |
Aptana (RadRails + RDT) | GPL, APL + CPL | Java | |
EasyEclipse for Ruby and Rails | Win 2000/XP, Linux, Mac OS X | ||
Eclipse + RDT | EPL + CPL | Java | |
Embarcadero TurboRuby | Проприетарная | Windows, OS X, Linux | |
FreeRIDE | Ruby License | Windows, OS X, POSIX | |
IntelliJ IDEA + Ruby plugin | Проприетарная (на IDEA), Apache 2.0 (на сам plugin) | Java, JRuby | Ruby plugin |
KDevelop | GNU GPL | Linux | |
Komodo Edit | Проприетарная | Windows, Mac, Linux | |
Mondrian Ruby IDE разработка прекращена, доступна старая версия | MIT | Ruby (+ FOX toolkit) | |
NetBeans IDE (версия 6.9.1 и более ранние) | CDDL | Java | Архивная копия от 1 августа 2008 на Wayback Machine |
RDE | Ruby License | Windows | (недоступная ссылка) |
Ruby in steel | Проприетарная | Visual Studio 2005 | |
RubyMine | Проприетарная (на базе IDEA) | Java | |
Visual Studio (реализация IronRuby) | Проприетарная | Windows | |
Xcode 3.1 | Проприетарная | Mac OS X 10.5 |
Кроме мощных возможностей, встроенных в язык, Ruby поставляется с большой стандартной библиотекой. Это, прежде всего, библиотеки для работы с различными сетевыми протоколами на стороне сервера и клиента, средства для работы с различными форматами представления данных (XML, XSLT, YAML, PDF, RSS, CSV, WSDL). Кроме встроенных в язык средств отладки, с Ruby поставляются библиотеки для модульного тестирования, журналирования, профилирования. Также есть библиотеки для работы с архивами, датами, кодировками, матрицами, средства для системного администрирования, распределённых вычислений, поддержки многопоточности и т. д.
Название | Описание | Версия[25] |
---|---|---|
Вершина иерархии классов Ruby. | 1.0 | |
Динамический массив для хранения произвольных объектов, индексируемый с 0. | 1.0 | |
Объекты сохраняют контекст выполнения некоторого участка кода (значение переменных, методов и т. д.). Может позже использоваться для выполнения вычислений в этом контексте. | 1.2 | |
Объект сохраняет адрес возврата и контекст выполнения, позволяя выполнить переход в точку создания из любого места программы (т. н. нелокальный переход). | 1.4 | |
Обёртка вокруг указателя Си, используется в основном при написании расширений. | 1.0 | |
Представление каталогов файловой системы. Предоставляет возможности для просмотра каталогов и их атрибутов. | 1.0 | |
Базовый класс всех исключений (образует вершину иерархии более чем 30 исключений). | 1.0 | |
Глобальная переменная false является единственным экземпляром этого класса и представляет логическую ложь в булевских выражениях. |
1.0 | |
Коллекция пар ключ-значение; порядок обхода не зависит от порядка вставки. | 1.0 | |
Базовые возможности ввода-вывода. | 1.0 | |
Класс для доступа к файлам. | 1.0 | |
|
Результат применения регулярного выражения. Обычно используется не напрямую, а через специальные переменные $& , $' , $` , $1 , $2 и т. д. |
1.0 |
Метод, ассоциированный с конкретным объектом (не с классом). Может использоваться для вызова этого метода без наличия объекта. | 1.2 | |
Класс модулей. | 1.0 | |
Класс классов; классы в Ruby являются объектами, а Class является классом этих объектов (метаклассом). | 1.0 | |
Единственным экземпляром класса является переменная nil . Только nil и false представляют ложь в программах. Любой другой объект представляет собой истину. |
1.0 | |
Абстрактный класс чисел. | 1.0 | |
Абстрактный класс целых чисел. Может трактоваться как бесконечная битовая строка для битовых операций. | 1.0 | |
Целые числа, ограниченные только количеством памяти. Конвертируется в Fixnum автоматически, если значение может быть размещено в них, и наоборот. (До версии 2.4) |
1.0 | |
Целые числа, которые могут быть размещены в машинном слове (32 бита для большинства машин). Если результат операции выходит за рамки, автоматически преобразуется в Bignum . (До версии 2.4) |
1.0 | |
Числа с плавающей запятой. | 1.0 | |
Блок кода со связанным с ним контекстом (замыкание), который может выполняться неоднократно в других контекстах. | 1.0 | |
Интервал: множество значений, заданных с начальным и конечным элементами. | 1.0 | |
Регулярное выражение. | 1.0 | |
Строка байт произвольной длины. | 1.0 | |
Предоставляет простой способ связывания атрибутов вместе без написания кода класса напрямую; генерирует специальные классы, содержащие множество переменных и методов доступа. | 1.0 | |
Представляет имя и создаётся при использовании синтаксиса :name . Все объекты с данным именем, созданные в программе, — ссылки на один объект. |
1.6 | |
Инкапсулирует информацию о потоке, включая основной поток скрипта Ruby. | 1.0 | |
Предоставляет способ управления группой потоков. Поток может принадлежать только к одной ThreadGroup . Добавление потока к новой группе удаляет его из любой предыдущей. |
1.6 | |
Дата и время. | 1.0 | |
Глобальная переменная true является единственной переменной класса и представляет логическую истину в булевских выражениях. |
1.0 | |
Метод, не связанный с конкретным объектом. Может привязываться к объекту и вызываться как Method . |
1.6 |
В языке Ruby осуществлён простой и удобный механизм для расширения языка с помощью библиотек, написанных на Си, позволяющий легко разрабатывать дополнительные библиотеки[26][27].
Для унифицированного доступа к базам данных разработана библиотека Ruby DBI (поддерживает SQLite, Oracle Database, ODBC, MySQL, DB2, MS SQL, InterBase, ADO и др.). Также существуют библиотеки для конкретных баз данных, поддерживающих специфические для них операции. Для реализации ORM существуют несколько библиотек, такие, как ActiveRecord, Mongoid, DataMapper или Sequel.
Среди графических библиотек — FxRuby (интерфейс к графической библиотеке FOX), графический пакет разработчика wxRuby (интерфейс к кроссплатформенному пакету wxWidgets на C++), QtRuby/Korundum (привязка к Qt и KDE соответственно), графические библиотеки для работы с Tk[28] и Gtk. Также реализована библиотека для работы с OpenGL, позволяющая программировать трёхмерную графику.
Win32utils — позволяет обращаться к специфическим возможностям Win32 API.
Rmagick — библиотека для работы с изображениями, поддерживающая более 90 форматов (основана на ImageMagick и GraphicsMagick).
Библиотека Ruport (Ruby reports) предназначена для лёгкой реализации отчётов и создания диаграмм на основе данных из БД или прямо из текстовых файлов CSV. Причём результаты можно сохранять в форматах PDF, HTML, CSV и TXT.
RuTils — обработчик русского текста на Ruby. Позволяет реализовать сумму прописью и выбор числительного. Например, 231.propisju(2) => «двести тридцать одна» или 341.propisju_items(1, «чемодан», «чемодана», «чемоданов») => «триста сорок один чемодан». А также перевод в транслит и работу с датами.
Для управления библиотеками и программами Ruby в виде самодостаточных пакетов предназначена система управления пакетами RubyGems (англ. gems, gem — драгоценный камень).
Существует всемирный репозиторий программного обеспечения Ruby RAA (Ruby Application Archive). Репозиторий по состоянию на сентябрь 2007 года насчитывает более полутора тысяч проектов. Большое количество программного обеспечения, написанного на Ruby, пользуется хостингом проекта RubyForge, созданного специально с этой целью. 15 мая 2014 года RubyForge закрыт, архив программ при этом останется доступен для скачивания.
Большинство расширений распространяются под свободными лицензиями (LGPL, лицензия Ruby) и могут быть использованы в любом проекте практически без ограничений.
Система RDoc предназначена для автоматического извлечения документации из исходных кодов и программ на Ruby и её дальнейшей обработки. Является стандартом де-факто для подготовки документации по программному обеспечению, написанному на Ruby.
Для доступа к документации Ruby из командной строки Unix разработана программа ri
.
С её помощью можно получить информацию о модулях, классах и методах Ruby.
Одним из наиболее часто критикуемых аспектов Ruby является производительность. Оригинальный интерпретатор в первых версиях показывал в тестах скорость работы в три-пять раз ниже, чем интерпретируемые языки, в то время находившиеся в активном использовании (PHP, JavaScript, Python). В настоящее время данная претензия в значительной мере потеряла актуальность: производительность современных версий интерпретаторов (как оригинального, так и альтернативных) примерно одного порядка (точные оценки разнятся от одного теста к другому) с близкими по целевому назначению интерпретируемыми языками, и в целом она достаточно высока для того, чтобы в типичных задачах интерпретатор не становился «узким местом». Внедрение JIT-компиляции в версии 2.6 соответствует общей тенденции повышения производительности интерпретаторов.
Ruby существенно уступает по скорости статически типизированным императивным языкам, компилируемым в объектный код, типа Си, Паскаля или Go, но данный недостаток — общий для большинства динамических языков. В тех случаях, когда производительность отдельных фрагментов программы становится критической, единственным способом её достижения является написание данных фрагментов на более быстрых языках (обычно — на Си).
Критики также указывают на недостатки имеющихся реализаций Ruby и самого процесса развития языка и системы.
Ruby используется в NASA, NOAA (национальная администрация по океану и атмосфере), Motorola и других крупных организациях[29]. Следующие программы используют Ruby как скриптовый язык для расширения возможностей программы или написаны на нём (частично или полностью).
В списке ниже перечислены лишь наиболее крупные обновления[32].
Название версии | Дата выхода | Примечания |
---|---|---|
0.06 | 7 января 1994 | Первая версия, указанная в Changelog’ах |
1.0-961225 | 25 декабря 1996 | Данная версия следовала сразу за версией 0.99.4-961224, выпущенной накануне. Номер после числа 1.0 — дата выпуска версии. Новые версии линейки 1.0 выходили ещё год (до 1.0-971225). |
1.1 alpha0 | 13 августа 1997 | Альфа-версии выходили вплоть до 7 октября 1997 (1.1 alpha9) |
1.1b0 | 4 декабря 1997 | Следующая версия после 1.1 alpha9. 27 февраля 1998 вышла версия 1.1b9, затем вплоть до середины 1998 выходили экспериментальные выпуски с обозначением вида 1.1b9_31 (версия 1.1b9_31 была выпущена, но в документации не отмечена). |
1.1c0 | 17 июля 1998 | Данная версия следовала за версией 1.1b9_31. Модификации этой версии выходили вплоть до 26 ноября 1998 (1.1c9). |
1.1d0 (pre1.2) | 16 декабря 1998 | Данная версия следовала за версией 1.1c9. 22 декабря 1998 была выпущена экспериментальная версия 1.1d1, завершившая данную линейку. |
1.2 (stable) | 25 декабря 1998 | В дальнейшем выходили модификации данной версии вплоть до версии 1.2.5, выпущенной 13 апреля 1999 года. 21 июня 1999 года была выпущена версия 1.2.6, объявленная как финальная версия 1.2 (1.2 final). 15 июля 1999 года вышла переупакованная (repacked) версия 1.2.6. |
1.3 (development) | 24 декабря 1998 | Отдельная ветка модификаций, разрабатываемая независимо от линейки 1.2 (по аналогии с ядром ОС Linux). Первая версия была объявлена как версия для разработки (development version) и следовала за версией 1.1d1. В дальнейшем последовало множество промежуточных модификаций: ruby-1.3.1-990215 — ruby-1.3.4-990625, после чего от указания даты в номере отказались и выпустили 1.3.5 — 1.4 alpha (15 июля 1999), 1.3.6 — 1.4 alpha (28 июля 1999), 1.3.7 — 1.4 beta (6 августа 1999). |
1.4.0 (stable) | 13 августа 1999 | Данная версия появилась через несколько дней после выхода 1.3.7 — 1.4 beta. В дальнейшем выходили новые модификации вплоть до версии 1.4.6, вышедшей 16 августа 2000 года. |
1.5.0 (development) | 20 ноября 1999 | Данная линейка предназначалась исключительно для проверки различных нововведений при разработке. Модификации данной линейки доступны исключительно в репозитории проекта и, соответственно, сборки данной версии на официальный сервер не выкладывались. |
1.6.0 (stable) | 19 сентября 2000 | В дальнейшем выпускались модификации этой версии вплоть до версии 1.6.8 (24 декабря 2002). 21 сентября 2005 года был выпущен патч для версии 1.6.8. |
1.7.0 (development) | 24 февраля 2001 | Данная линейка предназначалась исключительно для проверки различных нововведений при разработке. Модификации данной линейки доступны исключительно в репозитории проекта и, соответственно, сборки данной версии на официальный сервер не выкладывались. |
1.8.0 (stable) | 4 августа 2003 | В дальнейшем последовало большое число модификаций, которые выходят до сих пор (1 января 2011 года), например, промежуточная версия 1.8.7-p330 вышла 24 декабря 2010 года. |
1.9.0 (development) | 25 декабря 2007 | Изначально экспериментальная ветка, созданная для практической проверки ряда нововведений. |
1.9.3 (stable) | 31 октября 2011 | Отличия от 1.9.2 — существенны. |
2.0.0 (stable) | 24 февраля 2013 | |
2.1.0 (stable) | 25 декабря 2013 | |
2.2.0 (stable) | 25 декабря 2014 | Поддержка Unicode 7.0, добавлена сборка мусора для объектов типа Symbol. |
2.3.0 (stable) | 25 декабря 2015 | Добавлен новый оператор «&.» для упрощения обработки значений nil при обращении к объектам. Реализована новая экспериментальная прагма frozen-string-literal, позволяющая заморозить состояние строковых литералов в исходных текстах. |
2.4.0 (stable) | 25 декабря 2016 | Объединение Fixnum и Bignum в Integer. Поддержка изменения регистра знаков юникода для String. Улучшения хеш-таблиц (st_table). Интерактивные сессии binding.irb. Добавлен метод Regexp#match?. Оптимизация Array#max, Array#min. |
2.5.0 (stable) | 25 декабря 2017 | В блоках do/end теперь допустимо напрямую использовать секции rescue, else и ensure.
Определён метод yield_self для выполнение операции yield с блоком в его контексте. В отличие от tap, метод возвращает результат выполнения блока. Поддержка измерения покрытия тестовым кодом веток и методов. Добавлены новые методы Hash#slice и Hash#transform_keys. Включена автоматическая загрузка библиотеки pp.rb без необходимости указания в коде 'require «pp»'. Изменён на обратный порядок вывод трассировки и сообщения об ошибке (вначале идут вызовы, начиная со старых и заканчивая свежими, а в конце выводится сообщение об ошибке).[33] |
2.6.0 (stable) | 25 декабря 2018 | Добавлена поддержка JIT компиляции от Владимира Макарова;
Добавлен новый модуль RubyVM::AbstractSyntaxTree ; Новый алиас в ядре, Kernel#then алиас на Kernel#yield_self; Добавлены бесконечные интервалы (1..); |
2.7.0 (stable) | 25 декабря 2019 | Экспериментальная поддержка сопоставлений с образцом
Добавлен уплотняющий сборщик мусора GC.compact Возможность использования нумерованных имён переменных по умолчанию для параметров блока. Экспериментальная поддержка диапазонов без конечного значения. |
3.0.0 (stable) | 25 декабря 2020 | Добавлена возможность статического анализа |