在ruby中处理嵌套条件的最佳方法是什么?

时间:2015-02-28 10:02:07

标签: ruby idioms

我有以下逻辑:

if something
  some_variable = true if another_variable
  your_variable = true if that_other_variable
elsif thatthing
  my_variable = true if another_variable
  her_variable = true if that_other variable
else
  puts "nothing found"
end

这是极其简化的逻辑。请提前原谅vars的名字。

来自另一种语言,如果条件因可读性原因而不好,我已经考虑嵌套内联。我也对真实性类型测试有偏见。如果可能的话,我试图避免否定,但有时候它是不可避免的。

话虽这么说,我有几个常见的可能性,我可以用来取代内联ifs,以及一个更为罕见的,我把它放在一起以避免否定。我正在寻找反馈,以及你正在做的一些事情来解决这个问题。在这里:

可能性1:

三元:

if something
  some_variable = defined?(another_variable) ? true : false

可能性2:

否定:

if something
  some_variable = !defined?(another_variable)
# There are some variations to this, but this helps to address the negation I am trying to avoid.

可能性3(我赞成这个,但似乎有点不常见):

if something
  some_variable = (defined?(another_variable) && another_variable.length > 0)    # Two truth based tests (does the var exist, and is it greater than 0 in length) This returns true/false.

如果有人有任何其他解决方案,请告知我们,并且他们认为这是最惯用的解决方案。

谢谢!

2 个答案:

答案 0 :(得分:4)

好吧,我不会试图在评论中填写我的答案,而是回答一下,即使它不是一个回答"。

所有替代方案都不相同,它们都做不同的事情。你究竟想做什么?

 some_variable = true if another_variable

仅当some_variable = true具有真实值时才会设置another_variable。在ruby中,除了nilfalse之外的任何值在布尔测试中都被评估为true。 another_variable必须已经存在,否则您将获得异常。

  • 因此,如果another_variable存在且除nilfalse之外的任何内容,则您将some_variable设置为true。
  • 如果another_variable存在并且为nilfalse,则您无法在所有中更改some_variable 的值,它将保持不变。它将设置为false。 (如果some_variable已经存在,则nil值生成。否则,之前的值将保持不变)。
  • 如果another_variable根本不存在,则该语句将引发异常。

这是你想要的吗? (顺便说一句,使用这些毫无意义的变量名称会让你谈论你的例子更加困惑)。

如果这真的是你想要的(并且我怀疑它是什么),那么可能没有比你完成的方式更短或更清晰的方式来做到这一点:some_variable = true if another_variable

红宝石中的单行尾随if没有任何不恰当的内容,它完全不是惯用语,人们会一直这样做,因为它使代码更加清晰。在你的例子中 - 再次从你的假例子中很难说 - 我不认为它是单行的,如果这让人很难分辨出去了什么在这里,它是顶层条件的奇怪结构,代码本身的整体结构,很难说它应该做什么。但是你说你不想重构那个,所以没关系。也许这只是你试图产生一个简单的假设并提出一个非常混乱的假象,也许原始代码并不令人困惑。

您的其他替代示例其他,它们并不等同。例如:

some_variable = defined?(another_variable) ? true : false

这与您的第一个示例有不同的语义。

  • 如果所有都存在another_variable ,则some_variable将设置为true。即使another_variable存在值nilfalse。只要存在another_variablesome_variable就会设置为true。
  • 如果another_variable根本不存在some_variable,则设置为false。
  • 不存在some_variable不受影响的情况。

如果 真正打算做什么,那么肯定会有更简洁的选择。如果未定义变量,则defined?返回nil,否则返回解释已定义变量性质的字符串。如果要将其转换为严格布尔值truefalse,则可以使用双布尔否定:some_variable = !! defined?(another_variable)。回想一下,在ruby中,除falsenil之外的任何内容都在布尔上下文中被评估为真实,因此如果!! foo为{{1},false将变为foo如果nil是其他任何内容,则为{}}或false

人们也常常true并且认为它足以捕捉" foo存在",因为some_variable = defined?(another_variable)仍会被评估在布尔测试中相同。虽然真的,在惯用的ruby中,你偶尔只需要another_variable,但大多数情况下你正在处理你已经知道的变量,并且你不需要测试它们是否存在,甚至更少见您需要将该测试的结果存储在变量中。

您的其他示例再次具有不同的语义,其中没有一个实际上是等效的。希望我已经在这里给你提供工具,看看他们实际上做了什么。您也可以在一个小测试脚本或irb REPL中尝试全部。

我怀疑这些都不是你真正想要做的。这取决于你想要的实际语义,你还没有告诉我们。如果您开始使用的第一个版本确实代表了您想要的语义,那么我认为没有更短的方法可以做到这一点。

你说你正在重构现有的代码 - 基于这个例子,你给我们,我认为现有的代码可能是一团糟,其中有很多错误,写得很奇怪,并且缺乏对它的确切性和#因为你不是原始的开发者,所以甚至应该去做。我猜它也没有任何测试。在这种情况下,我首先编写一些测试来确定代码所谓的要执行的操作,然后您可以尝试重构并确保它仍然按预期执行。如果没有这个,并且有如此凌乱的代码,特别是对于ruby的新东西,你的重构很可能在你不打算时改变程序的语义,可能会引入新的甚至是陌生的bug。

答案 1 :(得分:2)

您不需要true if <var>部分,而是可以使用!!代替:

if something
  some_variable = !!another_variable
  your_variable = !!that_other_variable
elsif thatthing
  my_variable  = !!another_variable
  her_variable = !!that_other variable
else
  puts "nothing found"
end