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} #{code} 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, он уже будет правильно определен.
Данный текст является ознакомительным фрагментом.