-
Какие типы данных используются в Ruby? Что такое массив? хэш? строка? число? время? символ?
Ответ
Числа (
Numeric
) в Ruby выглядят так:5 # целое число Integer -12 # отрицательное целое число 076 # восьмеричное число 0b010 # двоичное число 0x89 # шестнадцатиричное число 4.5 # число с плавающей точкой Float 2+3i # комплексное число Complex Rational(2, 3) # рациональная дробь ⅔ Rational
Логический (булевый) тип — это вариация на тему «да» или «нет». В Ruby он представлен двумя предопределёнными переменными
true
(«истина» или «да») иfalse
(«ложь» или «нет»). Появляется логический тип в результате логических операций или вызова логических методов (обычно заканчиваются на знак вопроса?
).Чаще всего логический тип возникает как результат сравнения.
true
возвращает любой объект, в т.ч.0
, за исключениемfalse
иnil
(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", "Як-цуп-цоп, парви каридулла"]
Стро́ки (
String
) — это ряды букв и других символов. В Ruby стро́ки используют наработки языка Perl.Стро́ки начинаются и заканчиваются
"
(программистскими кавычками) или'
(машинописным апострофом).Чаще принято использовать одинарные кавычки. Однако в случае интерполяции и применении спецсимволов таких, как
\t
,\n
,'
используются двойные.Вот небольшой список их возможностей:
- Нет ограничений. Длина строки́ может достигать поистине фантастических размеров.
- Динамичность. Стро́ки можно расширять или уменьшать (для этого есть методы
+
и[]
). - Любой объект преобразуется в строку (методы
.inspect
и.to_s
есть у любого объекта). - Строка обладает обширной библиотекой методов, которые работают с правилами (это методы
.gsub
,.match
,.scan
,.split
). - Конкатенация и интерполяция
'2' + '2' #=> "22" # конкатенация name = 'Вася' "Привет, #{name}!" #=> "Привет, Вася" # интерполяция
Ассоциативные массивы (класс
Hash
) подобны массивам упорядоченных пар.Работают они подобно словарям: фигурная скобка символизирует боковой вид на открытую книгу, а стрелка
=>
покажет читателю связь каждой сущности с какой-то другой. Вторая фигурная скобка говорит, что пора закрывать книгу.Структурными элементами хеша являются ключи и соответствующие им значения.
hash = { "мама" => "мыла раму", 807 => "Это число улыбается!" } hash["мама"] #=> "мыла раму" hash["807"] #=> nil hash[807] #=> "Это число улыбается!"
При использовании хешей в качестве аргументов метода возможна запись без фигурных скобок, а если в качестве ключа используются символы, то и без стрелок.
Wife.new(age: 18, bust: 90, waist: 60, hips: 90)
Ассоциативные массивы оставляют возможность хранения данных разного типа только в ассоциативном виде.
Чтобы было удобней получать подмассив или подстроку, был введён тип данных — диапазон (класс
Range
).Диапазон формируется тремя элементами: начало, конец и тип протяжённости (символ
..
или...
).Начало и конец должны быть одного типа данных (одного класса) и быть перечислимыми, что значит, иметь метод
.succ
(succedent — «последующему»).Применение
..
подразумевает включение конечного элемента. Применение...
исключает конечный элемент.Пример диапазонов:
"a".."z" "a"..."z" # то же, что и "a".."y" 1..100 1...100 # то же, что и 1..99
Начиная с версии 2.6.0 вводится понятие бесконечного диапазона.
Пример применения:
array[3..] # возвратит массив с элементами array, соответствующие индексом от 3-го до последнего
В Ruby есть особый класс
Symbol
. Синтаксически объекты этого класса обозначаются двоеточием.Например,
:a
,:b
,:symbol
.Символ похож на строку (
String
). Одно из главных отличий заключается в том, что у каждого символа есть только один экземпляр.Что это означает на практике? И в чём отличие от строки?
Например, у нас есть такие объекты:
a = "slovo" b = "slovo" c = "slovo" d = :slovo e = :slovo f = :slovo
Дело в том, что в этом примере объекты
a
,b
иc
— это три разных объекта, они ссылаются на разные ячейки в памяти компьютера.А вот объекты
d
,e
иf
— это всё один объект. В этом легко убедиться:a.object_id #=> 47103948599080 b.object_id #=> 47103948574540 c.object_id #=> 47103948569400 d.object_id #=> 1294428 e.object_id #=> 1294428 f.object_id #=> 1294428
Символы часто используются в хэшах в качестве ключей. Одна из причин этого вытекает из свойств символов иметь лишь один экземпляр. Это позволяет экономить потребление памяти компьютера.
Ещё одно свойство символов — статичность. Т.е. к ним нельзя применить методы, подобные
downcase
или+
.И ещё одно важное применение символов, когда к ним применяется метод
to_proc
.downator = :downcase.to_proc downator.call('STROKA') #=> "stroka"
Как это работает? Дело в том, что в переменной
downator
хранится блокproc { |arg| arg.downcase }
На практике такое свойство часто применяют при операциях с массивами, например:
['STROKA', 'SLOVO'].map(&:downcase) #=> ["stroka", "slovo"]
-
Как хранится массив в памяти?
-
Какую структуру данных применить для проверки "парности скобок" вида
([])
и([[))
? -
Почему в Ruby
1660 / 100 ≠ 16.6
?Ответ
Если все аргументы арифметического выражения целые числа, то результат будет целым, если хотя бы одно число с плавающей запятой, то результат будет числом с плавающей запятой.Таким образом, чтобы получить
16.6
нужно чтобы одно из чисел имело типFloat
. -
Почему в Ruby
24.0 * 0.1 ≠ 2.4
?Ответ
Поскольку внутренне компьютеры используют формат (binary floating point), который не может точно представить число как 0.1, 0.2 или 0.3.Когда код компилируется или интерпретируется, ваш «0.1» уже округляется до ближайшего числа в этом формате, что приводит к небольшой ошибке округления даже до того, как произойдет вычисление.
https://floating-point-gui.de/basic/
https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#floats_imprecise
https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems
-
Какие структуры есть в ruby?
Ответ
Что такое struct, abstract, open struct Структуры в Руби следующие:struct
abstract
openstruct
Структуры позволяют так же работать с методами по примеру полного аналога класса. Полностью заменяют классы и возможно даже немного удобнее их. Но все пишут что не надо заменять структуры на классы полностью, они могут быть хороши только в не больших размерах и объемах коллекций.
struct и open struct это упрощенная форма создания классов, в котором мы указываем что должно быть передано в struct для вывода программы.
- struct — принимает четкое кол-во параметров для вывода программы.
person = :name, :age p.name = "Karthik" p.age = 30 puts "Hello, I am #{p.name}, age #{p.age}"
либо
person = :name, :age p = "Karthik", 30 puts "Hello, I am #{p.name}, age #{p.age}"
OpenStruct — не ругается, если параметров передано больше чем есть.
require 'ostruct' p.name= "Karthik" p.age = 30 puts "Hello, I am #{p.name}, age #{p.age}"
-
Что такое
loop
,while
,map
,each
?Ответ
loop
,while
— это управляющие конструкции, создающие циклы, повторение кода по условию/без условий.each
,map
— итераторы, перебирают все элементы у объекта (унаследованы отNumerable
).Итераторы — это методы, которые принимают блоки и выполняют код в блоках для элементов коллекций (массивов, интервалов или хэшей).
https://www.rubyguides.com/ruby-tutorial/loops/
https://www.rubyguides.com/2018/10/ruby-map-method/
http://rubycode.ru/ruby/osnovy/57-chislovye-iteratory.html
http://queirozf.com/entries/ruby-map-each-collect-inject-reject-select-quick-reference
-
Чем отличается
each
отmap
?Ответ
each
занимается просто перебором,map
занимается перебором и конечным выводом измененного массива, также можноmap
вызвать с помощью bang-метода для изменения исходного массива. -
Какие ещё циклы и итераторы есть в Ruby?
-
Назовите отличия
inject
иreduce
.Ответ
Это алиасы.
-
Какие переменные бывают, где они используются, где они доступны (поля видимости)?
Ответ
Локальные переменные
variable
— локальная переменная, она доступна только в той области видимости, где была определена.Переменные экземпляра класса
@variable
— доступны только в методах экземпляра класса, где они определены. При первом вызове возвращаютnil
.Глобальные переменные
$variable
— область видимости — вся программа (опасно использовать, т.к. потом сложно изменить, где и кто её поменял).Переменные класса
@@variable
— область видимости — класс в котором они определены и все экземпляры данного класса.http://rubycode.ru/ruby/osnovy/54-oblast-vidimosti-i-tipy-obektov.html
-
Что такое переменная с одной
@
и переменная с двумя@@
?Ответ
Переменные экземпляра класса
@variable
— начинаются с@
. Переменные экземпляра класса доступны в методах экземпляра класса, где они определены.Переменные класса
@@variable
— начинаются с двух символов@
. Их область видимости — класс в котором они определены и все экземпляры данного класса. -
Чем
require
отличается отrequire_relative
?Ответ
С возможностью указания абсолютного пути и относительного
require
подключает файлы/гемы по относительному пути в строгом соответствии./1/ruby.rb
, начиная с корня приложенияrequire_relative
подключает файлы без относительного пути и без указания разрешения файла, запускает прогу из той же директории, где лежит файл запускаrequire_relative '1/ruby.rb'
. -
Что такое гемы? Как с ними работать?
-
Как создать геттер и сеттер методы в ruby?
Ответ
C помощью методовattr_reader
attr_writer
attr_accessor
— объединяет attr_reader и attr_writer
class Tovar # Метод для установки цены def price=(price) @price = price end def price @price end end
http://rubyclub.blogspot.com/2012/10/ruby_15.html
http://findnerd.com/list/view/How-to-create-getter-and-setter-methods-in-Ruby/13615/
-
Что такое
attr_reader
,attr_writer
,attr_accessor
?Ответ
Все классы наследуют методы
Module
.attr_reader
,attr_writer
,attr_accessor
являются его методами.Что делают эти методы внутри класса?
attr_reader
создаёт переменную экземпляра и метод-геттер, который возвращает её значениеЭти записи эквивалентны:
attr_reader :name def name @name end
attr_writer
создаёт метод-сеттер, позволяющий изменять переменную экземпляра.Эти записи эквивалентны:
attr_writer :name def name=(name) @name = name end
attr_accessor
объединяет функционалattr_reader
иattr_writer
.http://ruby-doc.org/core-2.5.1/Module.html#method-i-attr_reader
http://ruby-doc.org/core-2.5.1/Module.html#method-i-attr_writer
http://ruby-doc.org/core-2.5.1/Module.html#method-i-attr_accessor
-
Что означает ключевое слово
self
?Ответ
self
относится к самому объекту, вызывает сам себя, без создания класса. Обычно применяется к методам внутри класса, чтобы можно вызвать без создания нового экземпляра класса.Так же можно сообщить что все методы будут
self
, делается с помощьюclass << self
. -
Что такое синглтон-методы и синглтон-классы?
Ответ
Синглтон-метод — метод, который может принадлежать только одному объекту. Это даёт возможность добавлять уникальное поведение отдельным объектам.cat = Animal.new dog = Animal.new def dog.barking 'WOOF! WOOF!' end dog.barking # => "WOOF! WOOF!" dog.singleton_methods # => [:barking] cat.barking # => NoMethodError (undefined method `barking' for #<Animal:0x000055a12143df38>) cat.singleton_methods # => []
Методы класса (
self
-методы) на самом деле тоже являются синглтон-методами классаClass
.Таким образом, в Руби все методы принадлежат какому-то классу.
Синглтон-класс — это анонимный класс, в котором размещаются синглтон-методы объекта.
dog.singleton_class # => #<Class:#<Animal:0x000055a121433970>> dog.singleton_class.method_defined?(:barking) # => true cat.singleton_class.method_defined?(:barking) # => false
Синглтон-класс встраивается в путь наследования и поиска метода интерпретатором Ruby.
dog.singleton_class.superclass # => Animal
Подробнее тут
-
Что такое
super
-методы и как они работают/где применяются?Ответ
`super` - ключевое слово, вызывает из родительского класса метод с аналогичным названием, что и метод вызывающий `super`. Применяется при переопределинии методов в дочерних классах.class Text def initialize(body:) @body = body end end class Note < Text def initialize(body:) super @date = Time.now end end # Если количество параметров в методе родительского и дочернего классов не совпадает # можно явно задать аргументы ключевому слову super class Article < Text def initialize(body:, title:) super(body: body) # Явное задание количества аргументов для super @title = title end end text = Text.new(body: 'Просто текст') note = Note.new(body: 'Заметка') article = Article.new(title: 'Статья', body: 'Текст статьи') p text #<Text:0x0000559cc64f3590 @body="Просто текст"> p note #<Note:0x0000559cc64f32e8 @body="Заметка", @date=2021-05-05 21:58:38.829037856 +0500> p article #<Article:0x0000559cc64f2e60 @body="Текст статьи", @title="Статья">
-
Что такое модуль в ruby? Какая разница между классом и модулем?
Ответ
Модули в Руби похожи на классы в том, что они содержат набор методов, константы, другие модули и определения классов.Модули задаются как классы, только слово
module
используется вместоclass
.В отличие от классов создать объекты на основе модуля нельзя, модуль не может иметь подклассы. Вместо этого вы добавляете недостающую функциональность класса или отдельного объекта с помощью модуля.
Модули — одиночки, нет иерархии и наследования.
-
Как организовано наследование в Ruby?
Ответ
Наследование в Ruby — прямое. У каждого класса может быть только один родительский класс.
Синтаксический сахар:
class Animal end class Dog < Animal end
В Ruby всё в конечном счёте принадлежит классу
BasicObject
.str = "Я - строка" str.class #=> String str.class.superclass #=> Object str.class.superclass.superclass #=> BasicObject
Однако в Ruby можно сымитировать множественное наследование с помощью модулей, подключая их при помощи include/extend.
-
Чем отличается
include
отextend
? Что такоеprepend
?Ответ
include
— необходимо создать экземпляр класса, чтобы задействовать логику модуля;extend
— позволяет включить дополнительное расширение или функциональность без создания экземпляра класса, непосредственно в используемом классе.
https://inet777.ru/comments/8436/metod-module-prepend-v-ruby-2
C помощью
prepend
методы модуля устанавливаются первоочередными при поиске метода в классе, в который включен модуль. -
Реализация множественного наследования в ruby?
Ответ
Реализация возможна через модули с помощью подключения
include
/extend
. -
Если в модуле сделать
extend self
, что произойдёт?Ответ
Как указано выше,
extend
позволяет подключить методы модуля к классу без создания экземпляра.Для модуля
self
— это сам модуль.Поэтому добавление
extend self
позволит использовать инстанс-методы модуля в качестве егоself
-методов.Без
extend self
:module MyModule def my_method puts 'Hello!' end end MyModule.my_method # undefined method `my_method' for MyModule:Module (NoMethodError)
После добавления:
module MyModule extend self def my_method puts 'Hello!' end end MyModule.my_method # Hello!
https://blog.bigbinary.com/2012/06/28/extend-self-in-ruby.html#so-how-does-extend-self-work
-
Какие есть способы вызова методов в ruby?
Ответ
-
.call
— не может вызвать методы без нового класса -
.send
— может вызвать методы без нового класса -
.eval
— не используется, так как очень медленный http://quabr.com/35400337/ruby-send-vs-call-method
-
-
Что такое
proc
,lambda
,block
? И какие отличия есть между ними?Ответ
Это анонимные функции, которые представляют из себя блоки.lambda
требует чтобы кол-во аргументов в блоке, соответствовало преданным в блок, так жеlambda
возвращает значение без блока, можно вызвать на переменной методcall
и передать к примеруreturn 'any'
,lambda
выведет.proc
не требует и может работать без передачи аргументов, но не может вызваться методомcall
и вернуть переданное значение методомreturn
.block
это кусочек ruby кода, который заключен в фигурные скобки и блок выполняется для каждого массива значений. -
Многопоточность в ruby?
-
Какие сервера бывают под Ruby?
Ответ
https://www.8host.com/blog/kratkij-obzor-veb-serverov-dlya-prilozhenij-ruby/
- WeBrick
- Phusion Passenger
- Puma
- Thin
- Unicorn
- Iodine
-
Что такое safe navigation?
Ответ
В новом синтаксисе выражение из примеров можно записать так:
image = user&.profile&.thumbnails&.large
Оператор применяется для сокращения выражений, где выполняется проверка существования объекта и затем обращение к методу объекта только в случае положительной проверки:
obj.nil? && obj.some_method
Вместе с лаконичным видом такая реализация дает быструю проверку на
nil
, так как изменения реализованы на уровне парсера и ruby-код в проверках не участвует. После того, как встретилсяnil
, дальнейшее выполнение цепочки прерывается. Проверка выполняется именно наnil
, а не на логическое условие, поэтому если результатом окажетсяfalse
, то выполнение будет успешно продолжено по цепочке дальше.Если в метод передаются аргументы, то, в отличие от
try
, они вычисляются только в том случае, если объект существует и метод реально вызывается. Например, для ActiveSupport в выраженииobj.try(:foo, bar())
всегда будет выполнятьсяbar()
, даже еслиobj
не существует. Но в выраженииobj&.foo(bar())
, аргументbar()
будет вычислен только тогда, когдаobj
не равенnil
.http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/
https://www.competa.com/blog/ruby-safe-navigation-operator-methods/
-
Как и чем проверить скорость работы методов? К примеру, что работает быстрее
each
,proc
илиlambda
?Ответ
Существуют гемы для сравнения скорости работы методов, например,
benchmark-ips
.С учётом особенностей синтаксиса гема пишется код, в котором тестируются выбранные методы. При запуске программа тестируют производительность методов с указанием разницы в процентах. https://github.com/evanphx/benchmark-ips
-
Какие существуют Ruby интерпретаторы?
Ответ
- CRuby
- MRI
- JRuby (MRi на базе JVM)
- Rubinius (реализация многопоточности на самом Ruby, достаточно успешная, но не без сайдэффектов)
- TruffleRuby
-
Что такое JIT?
Ответ
Just-In-Time (JIT) компиллятор оптимизирует, часто вызываемые методы. Таким образом, они будут запускаться быстрее в последующих вызовых. Главная цель JIT - это пропуск нескольких или всех шагов интерпретации.https://blog.heroku.com/ruby-just-in-time-compilation https://ru.wikipedia.org/wiki/JIT-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F https://www.youtube.com/watch?v=AJIAMT7ilHw
-
Какую сортировку использует метод
sort
в ruby?