Программирование на языке Ruby

На нашем литературном портале можно бесплатно читать книгу Программирование на языке Ruby, Фултон Хэл-- . Жанр: Программирование. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
Программирование на языке Ruby
Название: Программирование на языке Ruby
Дата добавления: 16 январь 2020
Количество просмотров: 525
Читать онлайн

Программирование на языке Ruby читать книгу онлайн

Программирование на языке Ruby - читать бесплатно онлайн , автор Фултон Хэл
Ruby — относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов. Книга является полноценным руководством по Ruby — ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа «как сделать то или иное в Ruby». В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии. Издание предназначено для программистов самого широкого круга и самой разной квалификации, желающих научиться качественно и профессионально работать на Ruby.

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

1 ... 73 74 75 76 77 78 79 80 81 ... 266 ВПЕРЕД
Перейти на страницу:

 break if eof?

 line = gets

 range = (line=~/=begin/)..(line=~/=end/)

 puts line if range

end

Чтобы понять, в чем дело, нужно осознать, что весь диапазон (включая обе границы) вычисляется на каждой итерации цикла, но с учетом внутреннего состояния. Поэтому оператор переключения — вообще не настоящий диапазон. Тот факт, что он выглядит похожим на диапазон, хотя по сути таковым не является, многие считают «злом».

И наконец, задумаемся о границах в операторе переключения. Они вычисляются каждый раз, но результат вычисления нельзя сохранить в переменной и затем просто подставить ее. В некотором смысле граничные точки оказываются похожи на объекты

proc
. Это не значения, а исполняемый код. Тот факт, что нечто, выглядящее как обычное выражение, на самом деле представляет собой
proc
, тоже не вызывает восторга.

И несмотря на все вышесказанное, функциональность-то полезная!.. Можно ли написать класс, который инкапсулирует ее, но при этом не будет таким «магическим»? Можно и даже не очень трудно. В листинге 6.1 приведен простой класс

Transition
, имитирующий поведение оператора переключения.

Листинг 6.1. Класс Transition

class Transition

 А, В = :А, :В

 T, F = true, false

 # state,p1,p2 => newstate, result

 Table = {[A,F,F]=>[A,F], [B,F,F]=>[B,T],

          [A,T,F]=>[B,T], [B,T,F]=>[B,T],

          [A,F,T]=>[A,F], [B,F,T]=>[A,T],

          [A,T,T]=>[A,T], [B,T,T]=>[A,T]}

 def initialize(proc1, proc2)

  @state = A

  @proc1, @proc2 = proc1, proc2

  check?

 end

 def check?

  p1 = @proc1.call ? T : F

  p2 = @proc2.call ? T : F

  @state, result = *Table[[@state,p1,p2]]

  return result

 end

end

В классе

Transition
для управления переходами применяется простой конечной автомат. Он инициализируется парой объектов
proc
(теми же, что для оператора переключения). Мы утратили небольшое удобство: все переменные (например,
line
), которые используются внутри этих объектов, должны уже находиться в области видимости. Зато теперь у нас есть решение, свободное от «магии», и все выражения ведут себя так, как в любом другом контексте Ruby.

Вот слегка измененный вариант того же подхода. Здесь метод

initialize
принимает
proc
и два произвольных выражения:

def initialize(var,flag1,flag2)

 @state = A

 @proc1 = proc { flag1 === var.call }

 @proc2 = proc { flag2 === var.call }

 check?

end

Оператор ветвящегося равенства проверяет соотношение между границами и переменной. Переменная обернута в объект

proc
, потому что мы передаем это значение только один раз, но хотим иметь возможность вычислять его повторно. Поскольку
proc
— замыкание, это не составляет проблемы. Вот как используется новая версия:

line = nil

trans = Transition.new(proc {line}, /=begin/, /=end/)

loop do break if eof? line = gets

 puts line if trans.check?

end

Я рекомендую именно такой подход, поскольку в нем все делается открыто, без привлечения «волшебства». Особую актуальность это приобретет, когда оператор переключения будет исключен из языка.

6.2.8. Нестандартные диапазоны

Рассмотрим пример диапазона, состоящего из произвольных объектов. В листинге 6.2 приведен класс для работы с римскими числами.

Листинг 6.2. Класс для работы с римскими числами

class Roman

 include Comparable

 I,IV,V,IX,X,XL,L,XC,C,CD,D,CM,M =

  1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000

 Values = %w[M CM D CD С XC L XL X IX V IV I]

 def Roman.encode(value)

  return "" if self == 0

  str = ""

  Values.each do |letters|

   rnum = const_get(letters)

   if value >= rnum

    return(letters + str=encode(value-rnum))

   end

  end

  str

 end

 def Roman.decode(rvalue)

  sum = 0

  letters = rvalue.split('')

  letters.each_with_index do |letter,i|

   this = const_get(letter)

   that = const_get(letters[i+1]) rescue 0

   op = that > this ? :- : :+

   sum = sum.send(op,this)

  end

  sum

 end

 def initialize(value)

  case value

   when String

    @roman = value

    @decimal = Roman.decode(@roman)

   when Symbol

1 ... 73 74 75 76 77 78 79 80 81 ... 266 ВПЕРЕД
Перейти на страницу:
Комментариев (0)
название