Язык Ruby Денис С. Мигинский
Ruby Создан Юкихиро Мацумото в 1995 г. В основу положены элементы языков Perl, Python, Lisp, Smalltalk и др., а также «принцип наименьшего удивления». Основные реализации:
Основные характеристики Ruby Динамический язык Сквозная объектная модель Поддержка исключений Автоматическая сборка мусора Поддержка метапрограммирования (в т.ч. интроспекция, evaluate) Поддержка элементов функционального программирования (блоки/замыкания, λ- выражения) Встроенная поддержка регулярных выражений
Hello, world! File.open(world_inhabitants.txt). readlines. each{|name| puts Hello, #{name}! }
Разделители выражений #комментарий a=1; b=2 #конец выражения, «;» можно не ставить c=a.to_f+ #выражение продолжается на следующей строке b.to_f d=a.to_f\ #явный перенос на следующую строку -b.to_f
Определения и вызовы функций def hello(name) puts Hello, #{name}! end hello(world) hello Gustav
Строки (String) name=Richard I phrase=Hello, #{name}! phraseWrong=Hello, #{name}! puts phrase #Hello, Richard I! puts phraseWrong #Hello, #{name}!
Интервалы (Range) finish=3 (1..finish).each{|i| puts i} # (1...finish).each{|i| puts i} # 1 2
Массивы (Array) a = [10, 15, 20, 5] puts a.max #20 b = [10, 30, Richard I] puts b.max #Ошибка времени выполнения c = Array.new(10){|i| i*i} puts c #
Ассоциативные массивы (Hash) price={apple=>10, durian=>100 } price[carrot]=5 price.each{|fruit,price| puts "#{fruit} - #{price} } #carrot – 5 #durian – 100 #apple – 10
Объектная модель Ruby В Ruby нет элементарных типов в обычном понимании, все является объектом. Для некоторых типов имеются специальные синтаксические конструкции, встроенные в язык: числа, строки, регулярные выражения, массивы, ассоциативные массивы, интервалы
Объектная форма операторов a = 1; b = 2; c = 3 d=a+b+c d=5.+(b).+(c) f=Proc.new{|name| puts Hello, #{name}!} f.call(Richard I)
Особенности объектной модели Ruby Отсутствие интерфейсов Одиночное наследование Поддержка «примесей» (mixins) Перегрузка операторов Специфический контроль доступа
Определение класса class Person #конструктор def initialize end #определение метода def info return age years" end
Аксессоры class Person #getters def end def end #setter (приватный в терминах Java/C++) protected def end
Методы и атрибуты класса class Person = 0 #атрибут класса def initialize end def Person.count #метод класса end
Наследование class Monarch < Person def initialize (name, dynasty, age) super(name, age) #вызов конструктора = dynasty end #переопределение метода info def info return House of +super end
Модификаторы доступа доступ к методам контролируется динамически, относительно объектов public – метод доступен всем protected – метод доступен всем объектам данного класса private – метод доступен только данному объекту (в т.ч. если он является экземпляром подкласса) все методы по умолчанию публичные все атрибуты приватные
Динамическое изменение модификаторов доступа #здесь метод age= защищенный class Person public :age=; end #метод стал публичным #без кода выше получим ошибку времени исполнения king=Person.new (Richard I, 820) king.age=830
Модули в качестве пространств имен module History class Person … end class Monarch
Модули в качестве примесей (mixin) module SignificantEvents def addEvent (…) … end class Person include SignificantEvents … end
Управляющие структуры: if, unless #постфиксная форма return 0 if a>0 return 0 unless a0 return 0 else return 1 end if a==0 then … elsif a
Где искать истину? Ложь: nil экземпляры FalseClass Истина: все остальное puts false.class #FalseClass puts true.class #TrueClass a=nil puts a ? true : false #false a=false puts a ? true : false #false a=0 puts a ? true : false #true
Управляющие структуры: case year = 1905 countryName = case year when then Russian Empire when then USSR else Russian Federation end #Russian Empire #применяется оператор === puts ( ) === 1905 #true puts ( ) == 1905 #false
Блоки и замыкания Блок – часть кода с собственным контекстом (т.е. изолированными локальными переменными). Блок как правило объявляется в одном контексте, а исполняется в другом. Блок может взаимодействовать с тем контекстом, в котором объявлен, т.е. является замыканием. Аналогом блока в Java является анонимный класс.
Применение блоков def nTimes (n) for i in (0...n) yield #вызов блока end nTimes(5) {puts Hello, world!}
Применение блоков class Integer def times (0...n).each {|i| yield} end 5.times {puts Hello, world!}
Определение и вызов блока def func (&block) #функция, вызывающая блок yield( ) #вызов блока с параметрами block.call( ) #--//-- end #передача блока в качестве параметра функции func {| | } #самостоятельное определение блока block=Proc.new {| | code} #вызов самостоятельно определеннорго блока block.call( )
Итераторы (2..5).inject(1){|f, i| f*=i} #120 == 5! (1..5).map {|i| i*i} #[1, 4, 9, 16, 25] File.open(world_inhabitants.txt). readlines. each{|name| puts Hello, #{name} }
module Enumerable: некоторые итераторы all? [{|obj| block } ] => true|false any? [{|obj| block } ] => true|false map {|obj| block } => array select {| obj | block } => array inject(initial){|memo, obj| block } => obj
Задача 1 Реализуйте класс, аналогичный Array, с многопоточной реализацией итераторов: map, any?, all?, select. Объясните, можно ли таким образом реализовать итератор inject? Дополнительные ограничения: не допускается использовать циклы; вся логика работы с потоками должны быть вынесена в отдельный метод, общий для всех итераторов.