在条件子句中赋值是否具有良好的ruby风格?

时间:2009-12-27 18:03:15

标签: ruby coding-style

为了更简洁地写,而不是这样做:

test_value = method_call_that_might_return_nil()
if test_value
  do_something_with test_value
end

我一直在条件中分配:

if test_value = method_call_that_might_return_nil()
  do_something_with test_value
end

这是不好的风格?更简洁的语法:

do_something_with test_value if test_value = method_call_that_might_return_nil()
根据Matz(in another SO question)的说法,不允许

,如http://redmine.ruby-lang.org/issues/show/1141所述,并且将在1.9中保持这种状态。

鉴于分配和比较可能存在混淆,这是否会使代码难以阅读?

8 个答案:

答案 0 :(得分:30)

It is explicitly GOOD style to use assignments in conditionals. If you do so, wrap the condition in parentheses.

# Bad

if value = Settings.get('test_setting')
  perform_action(value)
end

# Okay, but uncommon and verbose

value = Settings.get('test_setting')
if value
  perform_action(value)
end

# Good

if (value = Settings.get('test_setting'))
  perform_action(value)
end

See the community style guide for more information

答案 1 :(得分:28)

一个有点普遍的习惯用法是使用and,它看起来像这样:

tmp = method_call_that_might_return_nil and do_something_with tmp

另一种可能性是明确地调用#nil?,这样意图就会变得更加清晰;特别是很明显你实际上意味着分配而不是比较:

unless (tmp = method_call_that_might_return_nil).nil?
  do_something_with tmp
end

答案 2 :(得分:8)

简洁代码不一定是更好的代码。当Concision改进了从作者到未来维护者的预期代码行为的通信时,它很有用。我认为我们中的很多人都来自于我们在if块中意外分配的背景(当我们想要进行相等比较时),我们更喜欢样式,其中绝对清楚的是赋值是指,而不是比较。已经提到的.nil?成语具有该属性,并且我认为它比在if条件内具有明确赋值更清晰。但实际上,我没有看到为分配提供额外代码的危害。

答案 3 :(得分:5)

执行此操作的函数式编程方法是使用andand。这是一种链接方法调用的可读方式,因此中间的nil会阻止链。所以你的例子就像:

method_call_that_might_return_nil.andand.tap {|obj| do_something_with obj}
## or, in the common case: ##
method_call_that_might_return_nil.andand.do_something

答案 4 :(得分:3)

是的,我认为由于分配和比较之间可能存在混淆,这种风格很糟糕。分配然后进行测试只需要一行,并且它避免让将来认为这是一个错误并修补它以使用==

答案 5 :(得分:2)

C程序员做了很多。我不认为Ruby中有任何问题,只要它清楚发生了什么。

答案 6 :(得分:1)

我认为没关系。在条件中对赋值的厌恶来自于在键入时知道错过的键击==将比较转换为非预期的赋值。在某种情况下使用分配的风格禁止使得这种事故在眼睛中很突出(有时候对于语言而言,如在C中,如果在某种情况下遇到分配,可以使许多编译器发出警告)。另一方面,测试也使这些事故脱颖而出。如果您的代码完全被测试所覆盖,您可以考虑放弃此类禁令。

答案 7 :(得分:0)

由于警告,在 if 子句中执行赋值有一种很刺鼻的气味。如果您确实要处理 else 情况,那么 case ... in ... 模式匹配可以提供一些东西:

case method_call_that_might_return_nil
in nil
  # handle nil case
in test_value # pattern match to a new variable 
  # handle non-nil case with return value of method assigned to test_value
end

或者...

case method_call_that_might_return_nil
in test_value if test_value # pattern match to a new variable if not nil
  # handle non-nil case with return value of method assigned to test_value
else
  # handle nil case
end