Как сделать ленивую оценку аргументов Ruby
У меня есть код для проверки nil в ruby. Поэтому я хочу достичь этого:
например, если я вызываю get_score_value(nil,(nil-1))
. Я хочу, чтобы ruby задерживал оценку nil-1
, пока не достигнет функции get_score_value
, вместо того, чтобы оценивать ее до того, как она будет передана в функции. Другими словами, я хочу передать математическое выражение в качестве аргумента в метод.
Какой самый элегантный способ сделать это в рубине? Большое спасибо
def get_score_value(value,value2)
value.nil? ? "NULL" : value2.round(2)
end
UPDATE:
Я только понял, что этот вопрос действительно связан с темой ленивой и строгой оценки. (следующее из этого замечательного сайта:
http://www.khelll.com/blog/ruby/ruby-and-functional-programming/
Строгая и ленивая оценка
Строгая оценка всегда полностью оценивает аргументы функции перед вызовом функции. Ленивая оценка не оценивает аргументы функции, если их значения не требуются для оценки. Одно использование оценки Lazy - это увеличение производительности за счет исключения ненужных вычислений.
Однако, как показано в следующем примере, Ruby использует строгую стратегию оценки:
длина печати ([2 + 1, 3 * 2, 1/0, 5-4]) = > ZeroDivisionError: делится на 0
Третий параметр переданного массива содержит операцию деления на нуль и, поскольку Ruby выполняет строгую оценку, приведенный выше фрагмент кода вызывает исключение.
Ответы
Ответ 1
Вам может быть интересно использовать Proc...
func = Proc.new {|n| n -1 }
def get_score_value(value, proc)
if value.nil?
return proc.call(0)
end
end
p get_score_value(nil, func)
Ваш proc похож на обычный метод, он все равно может проверить нуль и все такое.
Или он позволяет вам предоставлять отдельные функции для обработки таких ситуаций:
func1 = Proc.new {|n| n -1 }
func2 = Proc.new { "was nil" }
def check_for_nil(value, funcNil, funcNotNil)
if value.nil?
return funcNil.call()
else
return funcNotNil.call(value)
end
end
p check_for_nil(nil, func2, func1)
p check_for_nil(1, func2, func1)
Также обратите внимание на потенциальное использование ключевого слова or
в случаях, когда вы просто хотите преобразовать его в пустой или стандартный тип ввода (т.е. использовать 0 для чисел, [] для массивов и т.д.)
def get_score_value(value)
(value or 0).round(2)
end
Ответ 2
Ruby-ish способ сделать это состоит в том, чтобы поместить ваше выражение в ваш блок методов и выполнить метод с условным выходом.
def f x
yield if x
end
x = nil
f x do
x - 1
end
Ответ 3
Вы можете использовать блок:
def get_score_value value
value.nil? ? "NULL" : yield
end
x = 1
puts get_score_value(x) { x-1 } #=> 0
x = nil
puts get_score_value(x) { x-1 } #=> "NULL"