Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:
Листинг 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

@roman = value.to_s

@decimal = Roman.decode(@roman)

when Numeric

@decimal = value

@roman = Roman.encode(@decimal)

end

 end

 def to_i

@decimal

 end

 def to_s

@roman

 end

 def succ

Roman.new(@decima1 +1)

 end

 def <=>(other)

self.to_i <=> other.to_i

 end

end

def Roman(val)

 Roman.new(val)

end

Сначала несколько слов о самом классе. Его конструктору можно передать строку, символ (представляющий число, записанное римскими цифрами) или

Fixnum
(число, записанное обычными арабскими цифрами). Внутри выполняется преобразование и сохраняются обе формы. Имеется вспомогательный метод
Roman
, это просто сокращенная запись вызова
Roman.new
. Методы класса
encode
и
decode
занимаются преобразованием из арабской формы в римскую и наоборот.

Поделиться:
Популярные книги

Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Ву Тим
Деловая литература:
о бизнесе популярно
5.00
рейтинг книги
Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Второй кощей

Билик Дмитрий Александрович
8. Бедовый
Фантастика:
юмористическое фэнтези
городское фэнтези
мистика
5.00
рейтинг книги
Второй кощей

Газлайтер. Том 27

Володин Григорий Григорьевич
27. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 27

Газлайтер. Том 29

Володин Григорий Григорьевич
29. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 29

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

Лекарь Империи 15

Карелин Сергей Витальевич
15. Лекарь Империи
Фантастика:
городское фэнтези
аниме
фэнтези
попаданцы
6.80
рейтинг книги
Лекарь Империи 15

Неудержимый. Книга XXIX

Боярский Андрей
29. Неудержимый
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Неудержимый. Книга XXIX

Кромешник. Том 1

Копьев Демьян
1. У черта на куличках!
Фантастика:
городское фэнтези
мистика
фэнтези
5.00
рейтинг книги
Кромешник. Том 1

Я до сих пор царь. Книга XXXII

Дрейк Сириус
32. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я до сих пор царь. Книга XXXII

Неучтенный элемент. Том 4

NikL
4. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 4

Кодекс Охотника. Книга XXXV

Винокуров Юрий
35. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXV

Курс 1. Сентябрь

Фокс Гарри
1. Маркатис
Фантастика:
аниме
фэнтези
сказочная фантастика
5.00
рейтинг книги
Курс 1. Сентябрь

Майами

Фишер Марк
Детективы:
триллеры
6.40
рейтинг книги
Майами

Вечный. Книга I

Рокотов Алексей
1. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга I