我有一个像臭的方法:
def search_record(*args)
record = expensive_operation_1(foo)
return record unless record.nil?
record = expensive_operation_2(foo, bar)
return record unless record.nil?
record = expensive_operation_3(baz)
return record unless record.nil?
record = expensive_operation_4(foo, baz)
return record unless record.nil?
end
对于“除非零”的“回复结果”,是否有一个好的红宝石成语?
或者我应该只写一个return_unless_nil(&blk)
方法?
(注意每个调用的args不同,所以我不能简单地迭代它们)
答案 0 :(得分:20)
您是否关心此处nil
和false
之间的区别?如果你只关心每个方法的返回值是否为“falsy”,那么这是一种非常Ruby的方式:
def search_record(*args)
expensive_operation_1(foo) ||
expensive_operation_2(foo, bar) ||
expensive_operation_3(baz) ||
expensive_operation_4(foo, baz)
end
如果您不熟悉这个习语,可以这样解释:Ruby,就像大多数语言一样,"short circuits" OR比较,这意味着如果第一个操作数评估为“truey”,它就不会费心去评估第二个操作数(即如果expensive_operation_1
返回除nil
或false
之外的其他内容,它将永远不会调用expensive_operation_2
),因为它已经知道布尔值的结果操作是真的。
Ruby所做的另一个有用的事情是,它不是从布尔运算中返回true
或false
,而是返回它评估的最后一个操作数。所以在这种情况下如果expensive_operation_1
返回nil
,它将调用expensive_operation_2
,如果返回一个值(不是假的),整个表达式将只计算为该值
最后,我们可以将这些布尔值链接起来,实际上,它将返回第一个不是假的操作数的结果,并且永远不会评估后续的操作数。如果操作数的所有评估为falsy,它将返回最后的操作数(我们知道它是假的,在你的情况下,可能是nil
)。
答案 1 :(得分:2)
补充Jordan的答案:让我们假设这些函数可以返回一个布尔值(不太可能是搜索函数,但无论如何)并且||
不起作用。然后我们可以使用所讨论的抽象here:
expensive_operation_1(foo).or_if(:nil?) do
expensive_operation_2(foo).or_if(:nil?) do
expensive_operation_3(foo).or_if(:nil?) do
expensive_operation_4(foo)
end
end
end