Ruby/Для ознакомления
Основные свойства Ruby
правитьИнтерпретируемый язык:
- Возможность прямых системных вызовов.
- Мощная поддержка операций со строками и правилами (регулярными выражениями).
- Мгновенное проявление изменений во время разработки.
- Отсутствие стадии компиляции.
Простое и быстрое программирование:
- Не надо объявлять переменные.
- Переменные динамически типизированы.
- Простой и последовательный синтаксис.
- присутствует сборщик мусора.
Объектно-ориентированное программирование:
- Всё есть объект. Даже имя класса есть экземпляр класса
Class
. - Классы, методы, наследование, полиморфизм, инкапсуляция и так далее.
- Методы-одиночки.
- Примеси при помощи модулей (возможность расширить класс без наследования);
- Итераторы и замыкания.
- Широкие возможности метапрограммирования.
Удобства:
- Неограниченный диапазон значений целых чисел.
- Модель обработки исключений.
- Все операторы возвращают значения, даже управляющие структуры.
- Динамическая загрузка.
- Механизм перехвата исключений.
- Поддержка потоков; как собственных, так и систем семейства UNIX.
Недостатки:
- Неуправляемость некоторых процессов (таких, как выделение памяти), невозможность задания низкоуровневых структур данных или подпрограмм;
- Невозможность компиляции и сопутствующей ей оптимизации программы;
- Открытость исходного кода даже в готовой программе (есть средство упаковки исходного кода в .exe-файл под Windows);
- Следствие двух первых недостатков — весьма низкая скорость запуска и выполнения программ.
Начало работы
правитьОт читателя требуется общее знание компьютеров, включая навыки работы с файловой системой и текстовыми файлами. Прежде чем начать программировать на Ruby, нужно установить интерпретатор и обустроить для себя удобную среду для создания программ. Для испытания кода из учебника можно воспользоваться сетевым интерактивным интерпретатором.
Об установке и настройке рабочей среды Ruby читайте приложение → Установка .
Программы на языке Ruby это текстовые файлы, не подлежащие компиляции. Для их исполнения нужен интерпретатор, который мы уже установили. Чтобы запустить программу на Ruby, необходимо вызвать интерпретатор и передать ему имя файла с программой в качестве параметра.
Чтобы запустить программу с именем Test_program.rb
(программы на Ruby обычно имеют расширение .rb
), в UNIX нужно вызвать консоль и набрать:
ruby Test_program.rb
Чтобы запустить программу из Windows нужно дважды кликнуть на файл с программой. Чтобы окно не исчезало и были видны результаты надо перед местами выхода из программы поставить команду ожидания ввода
STDIN.getc
Первая программа
правитьОткройте редактор и напишите программу. По традиции первая программа должна просто выводить приветствие миру:
puts "Hello, World!"
Сохраните её в файл helloworld.rb
и запустите. На экране будет красоваться надпись:
Hello, World!
На этом традиционную часть можно считать выполненной.
Полигон для испытания программ
правитьЧтобы посмотреть результат выполнения большинства примеров из учебника, не обязательно создавать файл. Достаточно использовать полигон для испытания программ на Ruby irb
, который входит во все дистрибутивы и сам написан на Ruby. Запускается он командой
irb
Полигон — это рубиговорящая командная строка. Она показывает вам результат выполнения каждой строки кода:
irb(main):001:0> [1, 2, 3, 4] =>[1, 2, 3, 4]
Поскольку любая функция в Ruby может быть переопределена в любой момент, важнейшая часть написания большинства небольших программ — это именно эксперименты на полигоне. Посмотрим, например, какие есть методы у обычной строки:
irb(main):002:0> "text".methods =>["methods", "instance_eval", "%", "rindex", "map", "<<", "split", "any?", …
Или посчитаем:
irb(main):003:0> 14 * 5 =>70
Для выхода с полигона — набрать exit
.
По причине того, что интерактивный терминал (полигон) поддерживает автозаполнение при введении табуляции, исходные тексты программ на Ruby принято «отбивать» пробелами (чтобы текст программы можно было просто скопировать в терминал и увидеть, как он работает). Если в irb
скопировать программу, «отбитую» табуляциями, интерактивный терминал будет прерывать каждую строчку ввода чтобы предложить варианты автозаполнения.
fxri: полигон и справочник
правитьВ последних версиях дистрибутива «Установка за один щелчок» для Windows появилась утилита fxri
. Это кроссплатформенное графическое приложение, вобравшее в себя функционал ri
и irb
. Буковки fx
в начале означают использование библиотеки FXRuby. Последние две буквы ri
означают Ruby Informer (Информатор о классах и методах в языке Ruby).
У fxri
три окна: в левом перечислены все методы c описаниями. Верхнее правое окно рассказывает о выбранном методе. Нижнее правое окно реализует программу irb
, описанную выше.
ruby browser
правитьЕсли вы работаете на Linux, вероятно в репозитории вашего дистрибутива найдется Ruby Browser. Приложение позволяет просматривать встроенную документацию на классы и модули Ruby. Та же документация доступна через консольную команду ri
.
puts 2.0 + 1.0
Комментарии и демонстрация результата
правитьКомментарием называется часть программного кода, пропускаемая при обработке (интерпретации или компиляции).
В Ruby знаком начала комментария служит #
. Всё, что между ним и концом строки, пропускается. Пример:
puts 2 + 2 # это комментарий
puts "Привет!" # тоже комментарий
Многострочные комментарии помещаются между словами =begin
и =end
=begin
Это длинный комментарий
Очень длинный
=end
puts "Привет!"
Результат иллюстрируемого кода будет располагаться после последовательности #=>
. Пример:
puts 2 + 2 #=> 4
puts "Привет" #=> Привет
Вывод на экран
правитьВ Ruby есть много методов вывода: print
, printf
, p
, puts
, .display
и другие. Но мы использовать будем два:
- метод
puts
. После вывода строки осуществляет переход на новую. Если приходится выводить объект, не являющийся строкой, тоputs
вызывает метод.to_s
для преобразования его к строке; - метод
p
. Имеет самое короткое название, из-за чего часто используется для отладки. Так же, как иputs
, делает перевод на новую строку после вывода. Перед выводом любого объекта (в том числе и строки) на экран, вызывает метод.inspect
.
Примеры вывода на экран:
puts [1, 2, 3, 4] #=> 1\n2\n3\n4
# \n означает перевод строки
p [1, 2, 3, 4] #=> [1, 2, 3, 4]
puts "Hello!" #=> Hello!
p "Hello!" #=> "Hello!"
puts 5 #=> 5
p 5 #=> 5
Как видно из примера, результаты во время вывода строк и массивов существенно различаются. Если вас не смущают кавычки в результате вывода, то смело используйте p
, если смущают, то puts
.
Иногда возникает ситуация, когда при попытке вывода на экран русскоязычной строки при помощи метода "\323\367\350\362\345 \320\363\341\350!" Чтобы избежать таких ситуаций следует поместить в начало программы следующий программный код: $KCODE = "u"
Кодировка UTF-8 используется в SciTE. При использовании других редакторов, может потребоваться смена кодировки на соответствующую (зависит от редактора и операционной системы) (Для версии ruby1.9.1. вместо$KCODE="u"
# coding: utf-8
который следует добавить в начало программы - прим. Sharipov.ru) |
Переменные
правитьПеременные используются, чтобы сохранить промежуточный результат вычислений. Имя переменной в Ruby должно:
- начинаться с буквы или знака подчёркивания;
- состоять из латинских букв, цифр или знака подчёркивания.
Примеры переменных:
array
variable
another_variable
3element # неправильное имя. Начинается с цифры
_3element # а вот как можно
__ # немного странное, но допустимое имя переменной
Переменная может иметь имя не только латинское, но и русское. Для этого, правда, требуется, чтобы весь текст программы был написан в кодировке UTF-8, а интерпретатор запускался с параметром -KU
.
Присваивание осуществляется знаком равенства (=
), вот так:
array = [1, 2, 3, 4]
variable = array + [1, 2]
another_variable = variable - array
То, что справа от =
, прежде чем стать значением переменной, обычно полностью вычисляется. Наша переменная variable
будет содержать массив [1, 2, 3, 4, 1, 2]
, потому что именно таков результат действия array + [1, 2]
. Плюс (+
) с массивами поступает именно так: прицепляет второй массив в хвост первого.
Переменная another_variable
теперь содержит пустой массив, поскольку операция минус убирает все вхождения элементов массива array
из массива variable
.
Переменные указывают на объект
правитьФокус-покус:
girlfriend = "Татьяна"
goes_on_a_visit = girlfriend
puts girlfriend #=> Татьяна
goes_on_a_visit[0] = "Б" # меняем первую (номер ноль) букву у переменной-строки
puts girlfriend #=> Батьяна
# На первый взгляд странно и неожиданно
Значение, возвращаемое первой переменной, изменилось потому, что в Ruby переменные содержат лишь ссылку на то, что вы им присваиваете.
Сами данные (объект) лежат где-то в другом месте. Ввиду этого естественно, что при прямом изменении самого объекта, на который указывает переменная, все другие переменные, указывающие на этот объект, будут возвращать изменённое значение (также будут изменяться).
Чтобы girlfriend
наша осталась "Татьяна"
, надо в переменную занести её клон:
girlfriend = "Татьяна"
goes_on_a_visit = girlfriend.clone
goes_on_a_visit[0] = "М" # Но изменили мы лишь клон. Дома в сохранности сидит настоящая:
puts girlfriend #=> Татьяна
Можно создавать копии объектов ещё методом .dup
. Разница между ними будет понятна позже.
Для безвредного присваивания новых значений переменным их редко приходится клонировать, ибо большинство методов делают это и так. Даже если вы просто присвоите переменной новое значение, Ruby создаст объект с новым значением и поместит в (уже существующую) переменную ссылку на тот объект:
# …
goes_on_a_visit = "Аристарх" # Создаётся новый объект, переменная переводится на него
p girlfriend #=> "Татьяна"
Базовые типы данных
правитьДанные любого типа в Ruby суть объекты тех или иных классов. Самые используемые встроенные типы данных:
Fixnum
(целые числа, меньше ),Bignum
(целые числа, больше ),Float
(числа с плавающей запятой),Array
(массивы),String
(строки),Hash
(ассоциативные массивы).
Естественно, что это только базовые типы, но их вполне хватает для широкого спектра задач.
Числа
правитьЧисла в Ruby выглядят так:
5 # целое число
-12 # отрицательное целое число
4.5 # число с плавающей точкой
076 # восьмеричное число
0b010 # двоичное число
0x89 # шестнадцатеричное число
Не будем пока углубляться и мельком взглянем на другие типы данных.
Логический тип
правитьЛогический (булевый) тип — это вариация на тему «да» или «нет». В Ruby он представлен двумя предопределёнными переменными true
(«истина» или «да») и false
(«ложь» или «нет»). Появляется логический тип в результате логических операций или вызова логических методов.
Чаще всего логический тип возникает как результат сравнения.
Название операции | Символ операции | Литерное обозначение |
---|---|---|
Или | || |
or
|
И | && |
and
|
Не | ! |
not
|
Исключающее или | ^ |
xor
|
Методы сравнения
правитьНазвание метода | Символ |
---|---|
Равно | ==
|
Не равно | !=
|
Меньше | <
|
Больше | >
|
Меньше или равно | <=
|
Больше или равно | >=
|
Часто молодые программисты, когда надо написать «меньше или равно», пишут знак =<
вместо <=
. Запомнить правильное написание можно вслух проговорив «меньше или равно» и в этом же порядке писать <
и =
.
- Традиционно имена логических методов заканчиваются на
?
(знак вопроса). - В качестве
false
может выступатьnil
, а в качествеtrue
— любой объект. nil
— это символ пустоты.
Массивы
правитьРазработчики Ruby решили не реализовывать особых классов для динамических массивов, списков, стеков и тому подобного. Они все это реализовали в массивах — структурах данных типа (или класса — в Ruby всё равно) Array
. Сделано это путём добавления специальных методов; например, методы .push
и .pop
для стека. Особенности массивов в Ruby:
- Нет ограничений (это общий принцип языка). Массивы могут быть сколь угодно длинными.
- Динамичность: размер массива легко меняется.
- Гетерогенность: один массив может хранить данные разных типов.
- Библиотека итераторов на каждый случай жизни. Эта возможность позволяет не использовать циклы для обработки данных в массивах, а, следовательно, избегать множества ошибок, связанных с неосторожным обращением с циклами. Итераторы реализуются на высочайшем уровне.
- Много других методов. Все элементарные задачи для массивов решаются вызовом нужного метода.
[1, 0, 740, 14, 25] # целочисленный массив
["a", "й", "6", 'Br', "Это массив строк, о них вы скоро узнаете"]
[[1, 2], [3, 4]] # двумерный целочисленный массив
# Матрица — это объект класса Matrix
# Двумерный массив — это не матрица целых чисел
["1-й элемент смешанного массива", "7.343", [4, "вепрь"],
[3, 67, 4326, 12, 3781357, 84221, "строка делает этот подмассив смешанным, но это не беда"]]
array = ["Этот массив пойдёт в переменную array", "Як-цуп-цоп, парви каридулла"]
Массив лучше всего вообразить как гусеницу или поезд с лапками-запятыми вместо колёс. Ползёт он всегда влево, на левом же конце его локомотив — первый элемент. Первый потому, что элементы упорядочены. Если знаете порядковый номер элемента, то легко получить его значение:
array[1] #=> "Як-цуп-цоп, парви каридулла"
В мире поездов-гусениц счёт вагонов начинается с локомотива, а не со следующего за ним вагона. Таким образом локомотив — это как бы нулевой вагон.
array[0] #=> "Этот массив пойдёт в переменную array"
Массивы кажутся странными с кавычками, но частенько бывают полезны при написании компьютерных программ. Возможно, вы даже поймёте, почему он ползёт всегда влево.
Строки
правитьСтро́ки — это ряды букв и других символов. В Ruby стро́ки используют наработки языка Perl. Вот небольшой список их возможностей:
- Нет ограничений. Длина строки́ может достигать поистине фантастических размеров.
- Динамичность. Стро́ки можно расширять или уменьшать (для этого есть методы
+
и[]
). - Любой объект преобразуется в строку (методы
.inspect
и.to_s
есть у любого объекта). - Строка обладает обширной библиотекой методов, которые работают с правилами (это методы
.gsub
,.match
,.scan
,.split
).
Правила — это новое название регулярных выражений. В текущей версии Ruby они называются регулярными выражениями, но давайте смотреть в будущее. Perl 6 уже не имеет понятия «регулярное выражение», заменив его «правилами» и «грамматиками». |
- Можно вставлять произвольныe переменные заключив их между
#{
и}
. Действует для строк начинающихся и заканчивающихся"
. После выполнения код заместится результатом.
Стро́ки начинаются и заканчиваются "
(программистскими кавычками) или '
(машинописным апострофом). Пример:
"мама мыла раму" # строка в кавычках
'рама сопротивлялась' # строка в апострофах
Стро́ки подобны массивам символов, поэтому их часто преобразуют к массивам, чтобы использовать богатый набор методов, а потом результат делают строкой.
Ассоциативные массивы
правитьАссоциативные массивы подобны массивам упорядоченных пар. Работают они подобно словарям: фигурная скобка символизирует боковой вид на открытую книгу, а стрелка =>
покажет читателю связь каждой сущности с какой-то другой. Вторая фигурная скобка говорит, что пора закрывать книгу. В Ruby такие массивы именуются Hash
hash = {"мама"=>"мыла раму", 807=>"Это число улыбается!"}
Но можно и без фигурных скобок, одной стрелкой:
"Превед"=>"Медвед"
Например:
puts hash["мама"] #=> мыла раму
puts hash["807"] #=> nil
puts hash[807] #=> Это число улыбается!
puts hash[1] #=> nil
puts hash["Превед"] #=> Медвед
Ассоциативные массивы оставляют возможность хранения данных разного типа только в ассоциативном виде.
Диапазоны значений
правитьЧтобы было удобней получать подмассив или подстроку, был введён простенький тип данных — диапазон (класс Range
). Диапазон формируется тремя элементами: начало, конец и тип протяжённости (символ ..
или ...
). Начало и конец должны быть одного типа данных (одного класса) и быть перечисляемыми, что значит, иметь метод .succ
. Пример диапазонов:
"a".."z"
"a"..."z" # то же, что и "a".."y"
1..100
1...100 # то же, что и 1..99
Диапазон-мотоцикл (..
) проезжает от первого указанного объекта к его .succ
(succedent — «последующему»), и до последнего включительно. Три точки — то же, но мотоцикл остановился прямо перед последним элементом. Ещё раз:
1..99
≣ 1...100
Объекты, имеющие .succ
называют последовательными: этим методом можно по текущему элементу достоверно определить следующий.
Классы и объекты
правитьСамодельные и неабстрактные составные типы данных называются классами. Если для вас это новость, то почитайте викиучебник об объектно-ориентированном программировании или статью в Википедии. Вообще, в Ruby всё в конечном счёте принадлежит классу Object
.
str = "Я - строка"
str.class #=> String
str.class.superclass #=> Object
Классы можно определять и создавать по ним объекты. Стоит отметить интересную особенность языка - описание класса здесь это не просто некая описательная конструкция, не имеющая типа (как, например, в C++), а это объект (!) класса Class, дополненный пользовательскими методами и полями. Внутри класса может быть много всего интересного, и у него может быть фамильное дерево, то есть классы Ruby поддерживают наследование. Однако заметим, что множественное наследование в Ruby не разрешается. И ещё много всего интересного можно сделать с классами и объектами. Но об этом позже.