我知道another answer中显示的优先级有所不同:
p foo = false || true
# => true
p foo = false or true
# => false
但似乎or
和||
之间存在更多不同之处。
例如:
p foo = 42 or raise "Something went wrong with foo"
# => 42
p foo = nil or raise "Something went wrong with foo"
# => Something went wrong with foo (RuntimeError)
p foo = 42 || raise "Something went wrong with foo"
# => syntax error, unexpected tOP_ASGN, expecting end-of-input
我期待得到:
p foo = 42 or raise "Something went wrong with foo"
# => 42
p foo = nil or raise "Something went wrong with foo"
# => Something went wrong with foo (RuntimeError)
p foo = 42 || raise "Something went wrong with foo"
# => Something went wrong with foo (RuntimeError)
但这是一个语法错误。那么发生了什么?
答案 0 :(得分:8)
这是Ruby的precedence table。
从此表中不清楚,但没有括号的Ruby方法调用的优先级低于||
和=
,但高于or
。请参阅此question。
因此,对于您的代码,从最高优先级到最低优先级:
||
=
raise "something"
or
or
foo = 42 or raise "Something went wrong with foo"
首先是=
:
( foo = 42 ) or raise "Something went wrong with foo"
然后raise
:
( foo = 42 ) or ( raise "Something went wrong with foo" )
然后or
:
( ( foo = 42 ) or ( raise "Something went wrong with foo" ) )
||
foo = 42 || raise "Something went wrong with foo"
首先是||
:
foo = ( 42 || raise ) "Something went wrong with foo"
这是您的语法错误!
你想:
foo = 42 || (raise "Something went wrong with foo") #=> 42
或
foo = 42 || raise("Something went wrong with foo") #=> 42
或只是
foo = 42 || raise
当您遇到优先事项时,应该小心添加另一个puts
或p
而不加括号!
例如:
p [1,2,3].map do |i|
i*2
end
输出:
#<Enumerator: [1, 2, 3]:map>
即使您可能已经预料到:
[2, 4, 6]
答案 1 :(得分:1)
||
和or
的操作不同。
第一个相当于方法调用,后者是控制流关键字。您可能总是希望使用||
来避免与优先级混淆。由于这个原因,Ruby的大多数样式指南都有一个禁止使用and
和or
的条款。
那么,
A or B
# can be considered equivalent to
if A then A else B end
,而
A || B
# can be considered equivalent to
A.or { B } # given a hypothetical "logical or" method
现在让我们看一下你的or
示例
p foo = false or true
相当于
temp = p(foo = false) # => nil
if temp
temp
else
true
end
因此在执行时会打印false
并返回true
[1] pry(main)> p foo = false or true
false
=> true
[2] pry(main)> foo
=> false
而
p foo = false || true
等同于(现在掩盖了布尔值和逻辑OR之间的差异,因为你的例子无论如何都在处理布尔值)
p(foo = false.|(true))
因此在执行时会打印true
并返回true
[1] pry(main)> p foo = false || true
true
=> true
[2] pry(main)> foo
=> true