如何对 Ruby 参数进行惰性求值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7031804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:44:52  来源:igfitidea点击:

How to do lazy evaluation of Ruby arguments

ruby-on-railsruby

提问by zsljulius

I have a code to do a check of nil in ruby. So what I want to achieve is this: for example, if I call get_score_value(nil,(nil-1)). I want ruby to delay the evaluation of nil-1till it reaches the get_score_valuefunction, instead of evaluate it before it got passed in the function. In another word, I want to pass a mathematical expression as an argument into a method. What is the most elegant way to do this in ruby? Thanks very much

我有一个代码来检查 ruby​​ 中的 nil。所以我想要实现的是:例如,如果我调用get_score_value(nil,(nil-1)). 我希望 ruby​​ 延迟评估nil-1直到它到达get_score_value函数,而不是在它传入函数之前评估它。换句话说,我想将一个数学表达式作为参数传递给一个方法。在 ruby​​ 中最优雅的方法是什么?非常感谢

def get_score_value(value,value2)
    value.nil? ? "NULL" : value2.round(2)
end

UPDATE:

更新:

I just realized this question is actually related to the topic of lazy and strict evaluation. ( the following is from this great site: http://www.khelll.com/blog/ruby/ruby-and-functional-programming/

我才意识到这个问题实际上与懒惰和严格评估的主题有关。(以下内容来自这个伟大的网站:http: //www.khell.com/blog/ruby/ruby-and-functional-programming/

Strict versus lazy evaluation

Strict evaluation always fully evaluates function arguments before invoking the function. Lazy evaluation does not evaluate function arguments unless their values are required to be evaluated. One use of Lazy evaluation is the performance increases due to avoiding unnecessary calculations.

However as the following example shows, Ruby use Strict evaluation strategy:

print length([2+1, 3*2, 1/0, 5-4]) =>ZeroDivisionError: divided by 0

The third parameter of the passed array contains a division by zero operation and as Ruby is doing strict evaluation, the above snippet of code will raise an exception.

严格评估与惰性评估

严格评估总是在调用函数之前完全评估函数参数。惰性求值不会求值函数参数,除非需要求值它们的值。延迟评估的一种用途是由于避免了不必要的计算而提高了性能。

但是,如下例所示,Ruby 使用 Strict 评估策略:

打印长度([2+1, 3*2, 1/0, 5-4]) => ZeroDivisionError: 除以 0

传递的数组的第三个参数包含除以零操作,并且由于 Ruby 正在执行严格评估,因此上面的代码片段将引发异常。

回答by drharris

You might be interested in using a Proc...

您可能有兴趣使用 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)

Your proc is like a normal method, it can still test for nil and things like that.

你的 proc 就像一个普通的方法,它仍然可以测试 nil 之类的东西。

Or, it allows you to provide separate functions to handle those situations:

或者,它允许您提供单独的函数来处理这些情况:

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)

Also note the potential use of the orkeyword in cases when you simply want to convert it to an empty or default type of the input (i.e. use 0 for numbers, [] for arrays, etc.)

另请注意,or在您只想将其转换为空或默认输入类型(即,对数字使用 0,对数组使用 [] 等)的情况下,该关键字的潜在用途

def get_score_value(value)
  (value or 0).round(2)
end

回答by DigitalRoss

The Ruby-ish way to do this is to put your expression in your method's block and have the method execute a conditional yield.

Ruby 风格的方法是将表达式放在方法的块中,并让方法执行有条件的 yield。

def f x
  yield if x
end

x = nil
f x do 
  x - 1
end

回答by Sony Santos

You can use a block:

您可以使用一个块:

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"