Программирование на языке Ruby
Программирование на языке Ruby читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
В листинге 11.15 представлена предложенная Джимом реализация генератора чисел Фибоначчи. Продолжения применяются для того, чтобы сохранить состояние между вызовами.
class Generator def initialize do_generation end def next callcc do |here| @main_context = here; @generator_context.call end end private def do_generation callcc do |context| @generator_context = context; return end generating_loop end def generate(value) callcc do |context| @generator_context = context; @main_context.call(value) end endend# Порождаем подкласс и определяем метод generating_loop.class FibGenerator < Generator def generating_loop generate(1) a, b = 1, 1 loop do generate(b) a, b = b, a+b end endend# Создаем объект этого класса...fib = FibGenerator.newputs fib.next # 1puts fib.next # 1puts fib.next # 2puts fib.next # 3puts fib.next # 5puts fib.next # 8puts fib.next # 13# И так далее...Есть, конечно, и более практичные применения продолжений. Один из примеров — каркас
BorgesSeasideПроблема в том, что продолжение — «дорогая» операция. Необходимо сохранить состояние и потратить заметное время на переключение контекста. Если производительность для вас критична, прибегайте к продолжениям с осторожностью.
11.2.6. Хранение кода в виде объекта
Неудивительно, что Ruby предлагает несколько вариантов хранения фрагмента кода в виде объекта. В этом разделе мы рассмотрим объекты
ProcMethodUnboundMethodВстроенный класс
ProcProcmyproc = Proc.new { |a| puts "Параметр равен #{а}" }myproc.call(99) # Параметр равен 99Кроме того, Ruby автоматически создает объект Proc, когда метод, последний параметр которого помечен амперсандом, вызывается с блоком в качестве параметра:
def take_block(x, &block) puts block.class x.times {|i| block[i, i*i] }endtake_block(3) { |n,s| puts "#{n} в квадрате равно #{s}" }В этом примере демонстрируется также применение квадратных скобок как синонима метода
callProc0 в квадрате 01 в квадрате 12 в квадрате 4Объект
Proc&myproc = proc { |n| print n, "... " }(1..3).each(&myproc) # 1... 2... 3...Ruby позволяет также превратить метод в объект. Исторически для этого применяется метод
Object#methodMethodstr = "cat"meth = str.method(:length)a = meth.call # 3 (длина "cat")str << "erpillar"b = meth.call # 11 (длина "caterpillar")str = "dog"# Обратите внимание на следующий вызов! Переменная str теперь ссылается# на новый объект ("dog"), но meth по-прежнему связан со старым объектом.с = meth.call # 11 (длина "caterpillar")Начиная с версии Ruby 1.6.2, можно также применять метод
Module#instance_methodUnboundMethodUnboundMethodMethod
