Ruby中圆括号的惯用法

22
array.include? 'foo' or array.include? 'bar'

这是一个语法错误(意外的关键字或)。添加括号可以解决该问题,但由于我对Ruby还很陌生,不知道以下两种方式哪种被认为更符合惯用法:

选项1

array.include?('foo') or array.include?('bar')

选项2

(array.include? 'foo') or (array.include? 'bar')

这是个人偏好问题,还是有一种方法被认为更“正确”?


2
这主要取决于个人喜好。 - Adam Eberlin
1
紧密相关的问题:https://dev59.com/a1vUa4cB1Zd3GeqPs2Bo - Andrew Grimm
第二个看起来像Lisp。 - anna328p
我们应该更加关注这个答案:https://dev59.com/7msz5IYBdhLWcg3wuKMm#7707910。特别是,需要注意的是,在Ruby中,“and”和“or”被设计为控制流语句。它们的低优先级使它们非常适合控制流,但通常不适用于布尔逻辑。这与括号问题无关,但由于问题询问了惯用方式,因此_Ruby惯用_的写法根本不涉及“or”;它应该使用“||”进行布尔逻辑。 - GrandOpener
4个回答

27
我建议你查看由社区驱动的Ruby编码风格指南,特别是语法部分。
对于属于内部DSL(例如Rake、Rails、RSpec)的方法、在Ruby中具有“关键字”状态的方法(例如attr_reader、puts)和属性访问方法,省略参数周围的括号。对于所有其他方法调用的参数,请使用括号。- 摘自指南
class Person
  attr_reader :name, :age

  # omitted
end

temperance = Person.new('Temperance', 30)
temperance.name

puts temperance.age

x = Math.sin(y)
array.delete(e)

这个答案需要更新。ruby-style-guide上的当前列表更加详细。validates(:name, presence: true) # 好的写法 validates :name, presence: true - tgf

4
你确定它失败了吗?你的初始示例在我这里运行得很好。
ruby-1.9.2-p290 :002 > array = ['bar']
 => ["bar"] 
ruby-1.9.2-p290 :003 > array.include? 'foo' or array.include? 'bar'
 => true

事实上,如果有什么东西可以被视为习惯用语,那就是其中一个。 or 的低优先级允许在不加括号的情况下工作。这种特性应该使它成为 Ruby(甚至 Perl)的习惯用法。
选项1非常清晰,但考虑到您包含了括号,您真的没有必要使用 or。使用 || 可能更好,因为它具有像其他运算符一样的高优先级,并且更常见。我认为出于看起来像英语的目的而使用 or 不是一个好的做法。它在语言中有语义意义,最好用于那些特点。
当然,选项2是愚蠢的。如果要包含括号,最好将其用于方法签名。
希望这可以帮助您。

2
结果 = array.include? 'foo' 或者 array.include? 'bar' 不起作用,所以你的方法并没有什么帮助。你需要在某个地方添加一些括号。 - Andrew Grimm
3
运算符优先级再次给人们带来了麻烦。你看,=的优先级高于or,所以当你这样写时,你实际上是在说(result = array.include? 'foo') or array.include? 'bar'。显然,这会导致失败。条件语句可以正常工作(例如if ...; ... end),如果你将整个表达式用括号括起来也可以。这就是or的使用场景,但完全可以避免使用它。我几乎从不使用它。最终,行为驱动开发和证明代码的正确性是值得的。这使你可以自由地玩耍你的实现,而这才是 Ruby 的真正乐趣。 - Blake Taylor
安德鲁:那正是我的问题。布莱克:感谢您的解释。我想我需要一些时间才能真正理解这里发生了什么。希望在六个月后回顾这个帖子时,一切都变得清晰明了。 :) - davidchambers
请注意,我的上一条评论中有一个错误。这不是 Ruby 解释该语句的方式,实际上它可以工作... 无论如何,在这里有一个关于使用 andor 的很好的介绍。http://avdi.org/devblog/2010/08/02/using-and-and-or-in-ruby/ 对于任何困惑,我表示抱歉。 - Blake Taylor

4

Avdi Grimm认为你不应该使用andor进行布尔逻辑运算。你只应该在控制流(类似于ifunless)中使用andor

根据他的建议,你应该使用||代替:

array.include?('foo') || array.include?('bar')

你可以将你的例子表述为:“如果数组包含'foo',或者如果数组包含'bar'”。在这种情况下,“or”是可以使用的。如果你想要表达“如果数组等于'foo'或'bar'”,你需要使用||运算符:if array == 'foo' || 'bar'。在这种情况下,如果你用or替换||,它总是会通过,因为你会说“如果数组是'foo',或者如果'bar'返回true。”你可以把它想象成,在假定的括号内使用||,而在外面使用orif (array == 'foo' || 'bar')if (array == 'foo') or 'bar'。我希望这能更清楚地解释一些。 - bricker

2
选项1更受欢迎,因为它也适用于其他语言。选项2看起来像LISP,而现在不太流行。

2
很遗憾,你说的Lisp是对的——这是我使用过的最高效的语言。可惜年轻的程序员害怕它(或者更糟糕的是:甚至不知道它的存在)。 - SMBiggs
Lisp 的话前面会有一个 or :) - Rob Grant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接