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

1.4.1. Кодирование во время выполнения

1.4.1. Кодирование во время выполнения

Мы уже упоминали директивы load и require. Важно понимать, что это не встроенные предложения и не управляющие конструкции; на самом деле это методы. Поэтому их можно вызывать, передавая переменные или выражения как параметры, в том числе условно. Сравните с директивой #include в языках С и C++, которая обрабатывается во время компиляции.

Код можно строить и интерпретировать по частям. В качестве несколько искусственного примера рассмотрим приведенный ниже метод calculate и вызывающий его код:

def calculate(op1, operator, op2)
 string = op1.to_s + operator + op2.to_s
 # Предполагается, что operator - строка; построим длинную
 # строку, состоящую из оператора и операндов.
 eval(string)                    # Вычисляем и возвращаем значение.
end
@alpha = 25
@beta = 12
puts calculate(2, "+",2)         # Печатается 4
puts calculate(5, "*", "@alpha") # Печатается 125
puts calculate("@beta", "**", 3) # Печатается 1728

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

puts "Имя метода: "
meth_name = gets
puts "Строка кода: "
code = gets
string = %[def #{meth_name}n #{code}n end] # Строим строку.
eval(string) # Определяем метод.
eval(meth_name) # Вызываем метод.

Зачастую необходимо написать программу, которая могла бы работать на разных платформах или при разных условиях, но при этом сохранить общий набор исходных текстов. Для этого в языке С применяются директивы #ifdef, но в Ruby все определения исполняются. Не существует такого понятия, как «этап компиляции»; все конструкции динамические, а не статические. Поэтому для принятия решения такого рода мы можем просто вычислить условие во время выполнения:

if platform == Windows
 action1
elsif platform == Linux
 action2
else
 default_action
end

Конечно, за такое кодирование приходится расплачиваться некоторым снижением производительности, поскольку иногда условие вычисляется много раз. Но рассмотрим следующий пример, который делает практически то же самое, однако весь платформенно-зависимый код помещен в один метод, имя которого от платформы не зависит:

if platform == Windows
 def my_action
  action1
 end
 elsif platform == Linux
 def my_action
  action2
 end
 else
 def my_action
  default_action
 end
end

Таким способом мы достигаем желаемого результата, но условие вычисляется только один раз. Когда программа вызовет метод my_action, он уже будет правильно определен.

Оглавление книги


Генерация: 0.316. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз