在Ruby中,“or”和“||”有什么区别?

211

or|| 运算符在 Ruby 中有什么区别?还是只是个人偏好?


5
请参阅“and”和“&&”之间的区别 - Andrew Marshall
1
有关语义,请参见Avdi Grimm的Ruby中使用“and”和“or” - Stefan
8个回答

301

这是一个操作符优先级的问题。

|| 的优先级高于 or

在两者之间,你还有其他操作符,包括三目运算符 (? :) 和赋值运算符 (=),所以你选择哪个可能会影响语句的结果。

这里有一个Ruby 操作符优先级表

参见这个问题,了解使用 and/&& 的另一个例子。

此外,请注意一些可能发生的恶性事件:

a = false || true  #=> true
a  #=> true

a = false or true  #=> true
a  #=> false

前两个语句的结果都是true,但第二个语句将a设置为false,因为=优先级低于||但高于or


90

正如其他人已经解释的那样,唯一的区别是优先级。但是,我想指出这两者实际上有两个不同之处:

  1. andornot 的优先级比 &&||! 要低得多
  2. andor 的优先级相同,而 && 的优先级高于 ||

一般来说,避免使用 andornot ,而改用 &&||! 更具良好的编程风格。(例如Rails核心开发人员拒绝使用关键字形式而非运算符形式的修补程序。)

它们存在的原因并非是用于布尔公式,而是用于控制流程。它们通过Perl的众所周知的 do_this or do_that 惯用语进入Ruby,其中,如果存在错误,则 do_this 返回 falsenil,然后才会执行 do_that。(类似的,还有 do_this and then_do_that 惯用语。)

示例:

download_file_via_fast_connection or download_via_slow_connection
download_latest_currency_rates and store_them_in_the_cache
有时,这会使控制流比使用ifunless更加流畅。
很容易看出为什么在这种情况下运算符具有“错误”的(即相同的)优先级:它们永远不会在同一表达式中同时出现。当它们确实一起出现时,通常希望它们简单地从左到右进行评估。

3
有时我会被这个搞糊涂,因为在Perl中,“and”的优先级确实比“or”高,反映了“&&”和“||”。但通常你不应该把长而复杂的这些串联在一起。 - ephemient
20
不要听@MarnenLaibow-Koser的话 - 这与可读性无关,而与优先级差异有关,在最基本的布尔运算中将产生不同的结果:例如 true && false != true and falsefalse or true != false || true - Yarin
2
@Yarin 只有在你开始嵌套操作而不使用括号时,优先级才会成为问题。你的例子 true && false 实际上基本等价于 true and false,因为没有优先级问题。同样地,(x > 1) and (x < 4) 在操作上等价于 (x > 1) && (x < 4),因为所有的优先级都是通过括号完成的。在这些情况下,选择仅仅是一个可读性问题。 - Marnen Laibow-Koser
2
@Yarin,实际上,你的例子并没有展示出你认为的那样。true && false 等同于 true and false。你例子中的差异仅仅是由于隐式优先级问题造成的:print true and false 等同于 print(true) and false,而 print true && false 等同于 print(true && false)。你已经很好地证明了我的观点——只有在遇到没有括号的操作时,优先级才会发挥作用。 - Marnen Laibow-Koser
2
@Yarin 看来我在这里说错了一半;似乎 print(true and false) 是一个语法错误,这是我之前没有意识到的。 - Marnen Laibow-Koser
显示剩余5条评论

44

and/or 是用于控制流程的。

Ruby 不允许以下语法:

false || raise "Error"

然而这是有效的:

false or raise "Error"
你可以使用 () 来完成第一项工作,但使用 or 是正确的方法。
false || (raise "Error")

1
想知道为什么这个被踩了。第二个最佳答案说“唯一的区别是优先级”,但是通过我的例子,你可以看到那并不是这样。 - Eadz
这确实清楚地证明了被接受的答案是(微微)错误的。据您所知,您在此展示的行为是否有记录在案? - Mark Amery
5
无效语法是操作符优先级的结果。raise不会返回,因此无法作为表达式进行评估。 - bluehallu

15

puts false or true --> 输出:false

puts false || true --> 输出:true


那是如果你将它传递给一个方法。单独使用它总是返回true。 - Paul Brunache

10

我使用这些运算符的方式:

||, && 用于布尔逻辑。 or, and 用于控制流程。例如:

如果可能 || 可能,那么 do_smth - 我们在此处评估条件。

do_smth or do_smth_else - 我们定义工作流程,与 unless do_smth do_smth_else 等效。

举个简单的例子:

> puts "a" && "b"
b

> puts 'a' and 'b'
a
Rails中一个常见的习语是render and return。它是一个快捷方式,相当于说return if render,而render && return则不起作用。有关更多信息,请参见Rails文档中的"避免双重渲染错误"。

1
感谢您解释or运算符的作用 :) - jayqui

2

or||是不同的。请使用||运算符而不是or运算符。

以下是一些原因:

  • or运算符的优先级低于||
  • or的优先级低于赋值运算符=
  • andor的优先级相同,而&&的优先级高于||

我强烈不同意这个观点;andor在控制流中确实有它们的用处;例如,你可以写成if a==b and c==d,并且你可以确定and具有最低的优先级。对于来自C语言以外的人来说,这看起来也更加美观。 - DarkWiiPlayer

1

or||都在其中一个操作数为真时返回真。它们只有在第一个操作数为假时才会计算第二个操作数。

and一样,or||唯一的区别是它们的优先级不同。

有趣的是andor优先级相同,而&&的优先级高于||


1
不是这样的。a = false or true,a将被赋值为false - Anwar

-15
只是为了补充mopoke的回答,这也涉及到语义问题。使用or被认为是一种良好的实践,因为它比||更易读。

3
我不确定“良好实践”是站在或运算符的哪一边。这种情况类似于在参数上使用括号。在某些情况下,方法调用没有括号会更易读,但在特定情况下会导致奇怪的错误。我曾选择性地使用or并且去掉括号,但最终我放弃了它们,因为相当多的情况下不能使用,有些时候我会忘记并引入错误,并且我更喜欢始终使用括号和||的一致性。至少这种情况存在争议。 - tfwright
你的意思是这只是语法问题吧 :) 它们都有相同的语义解释(模运算符优先级) - klochner
3
如果你在布尔运算中依赖于优先级,那么你的代码本来就不易读。添加括号或进行重构。 - Marnen Laibow-Koser
这应该是一条注释,而不是一个答案。 - the Tin Man

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