Ruby
Материал из Викиучебника
Человек создан для творчества, и я всегда знал, что люблю творить. Увы, я обделён талантом художника или музыканта. Зато умею писать программы.
Я хочу, чтобы компьютер был моим слугой, а не господином, поэтому я должен уметь быстро и эффективно объяснить ему, что делать.
Программы должны быть написаны так, чтобы их могли читать люди, и лишь иногда так, чтобы их могли выполнять машины.
Абельсон и Сассман
Ру́би — интерпретируемый язык программирования высокого уровня. Обладает независимой от операционной системы реализацией многопоточности, строгой динамической типизацией, «сборщиком мусора» и многими другими возможностями, поддерживающими много разных парадигм программирования, прежде всего классово-объектную. Ruby был задуман в 1993 году (24 февраля) японцем Юкихиро Мацумото, стремившимся создать язык, совмещающий все качества других языков, способствующие облегчению труда программиста.
Этот учебник намерен осветить все тонкости программирования на Ruby. Повествование идёт «по спирали»: начиная с самых общих понятий, темы рассматриваются по нескольку раз с нарастающей подробностью.
Учебник пока неполон. Читайте иноязычную литературу по 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 нет под рукой, приходится использовать сетевой полигон. Он позволяет выполнять код на Ruby прямо из браузера.
[править] Комментарии и демонстрация результата
Комментарием называется часть программного кода, пропускаемая при обработке (интерпретации или компиляции).
В Ruby знаком начала комментария служит #. Всё, что между ним и концом строки пропускается. Пример:
puts 2 + 2 # это комментарий 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 = "utf-8" Кодировка UTF-8 используется в SciTE. При использовании других редакторов, может потребоваться смена кодировки на соответствующую (зависит от редактора и операционной системы). |
[править] Переменные
Переменные используются, чтобы сохранить промежуточный результат вычислений. Имя переменной в Ruby должно:
- начинаться со строчной буквы или знака подчёркивания;
- состоять из латинских букв, цифр и знака подчёркивания.
Примеры переменных:
array variable another_variable Wrong_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]. Плюс (+) с массивами поступает именно так: прицепляет второй массив в хвост первого.
[править] Переменные указывают на объект
Фокус-покус:
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 (целые числа, меньшие 231), Bignum (целые числа, большие 231), 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, 88] # целочисленный массив ["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 уже не имеет понятия «регулярное выражение», заменив его «правилами» и «грамматиками». |
- Можно вставлять произвольный код на языке Ruby в строку. После выполнения код заместится результатом.
Стро́ки начинаются и заканчиваются " (программистскими кавычками) или ' (машинописным апострофом). Пример:
"мама мыла раму" # строка в кавычках 'рама сопротивлялась' # строка в апострофах
Стро́ки подобны массивам символов, поэтому их часто преобразуют к массивам, чтобы использовать богатый набор методов, а потом результат делают строкой.
[править] Ассоциативные массивы
Ассоциативные массивы подобны массивам упорядоченных пар. Работают они подобно словарям: фигурная скобка символизирует боковой вид на открытую книгу, а стрелка => покажет читателю связь каждого одного с чем-то другим. Вторая фигурная скобка говорит, что пора закрывать книгу.
{"мама"=>"мыла раму", 807=>"Это число улыбается!"}
Но можно и без фигурных скобок, одной стрелкой:
"Превед"=>"Медвед"
Например:
puts array["мама"] #=> мыла раму puts array["807"] #=> nil puts array[807] #=> Это число улыбается! puts array[1] #=> nil puts array["Превед"] #=> Медвед
Ассоциативные массивы оставляют возможность хранения данных разного типа только в ассоциативном виде.
[править] Диапазоны значений
Чтобы было удобней получать подмассив или подстроку, был введён простенький тип данных — диапазон (класс Range). Диапазон формируется трёмя элементами: начало, конец и тип протяжённости (символ .. или ...). Начало и конец должны быть одного типа данных (одного класса) и быть перечислимыми, что значит, иметь метод .succ. Пример диапазонов:
"a".."z" "a"..."z" # то же, что и "a".."y" 1..100 1...100 # то же, что и 1..99
Диапазон-мотоцикл (..) проезжает от первого указанного объекта к его .succ (succedent — «последующему»), и до последнего включительно. Три точки — то же, но мотоцикл остановился прямо перед последним элементом. Ещё раз:
1..99 ≣ 1...100
Объекты, имеющие .succ называют последовательными: этим методом можно по текущему элементу достоверно определить следующий.
[править] Классы и объекты
Самодельные и неабстрактные составные типы данных называются классами. Если для вас это новость, то почитайте викиучебник об объектно-ориентированном программировании или статью в Википедии. Вообще, в Ruby всё в конечном счёте принадлежит классу Object.
str = "Aз есмь строка" str.class #=> String str.class.superclass #=> Object
Классы можно определять и создавать по ним объекты. Внутри класса может быть много всего интересного, и у него может быть фамильное дерево, то есть классы Ruby поддерживают наследование. Однако заметим, что множественное наследование в Ruby не разрешается. И ещё много всего интересного можно сделать с классами и объектами. Но
