Подтвердить что ты не робот

Как сделать ленивую оценку аргументов 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 выполняет строгую оценку, приведенный выше фрагмент кода вызывает исключение.

4b9b3361

Ответ 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"