当我这样做时:
puts(nil or 4)
Ruby抱怨:
SyntaxError: syntax error, unexpected keyword_or, expecting ')'
为什么? puts(nil || 4)
确实有用,但我想知道为什么or
没有。我认为两者之间的区别只在于它们的运算符优先级。
(我知道表达式nil or 4
似乎没有用,因为它总是返回4
。这只是一个例子,为了简单起见。我的实际情况。表达式为Integer(ENV['WD'] or 4)
。)
答案 0 :(得分:15)
因为这是ruby语法的原因。
and
/ or
个关键字旨在用于控制流结构。考虑这个例子:
def die(msg)
puts "Exited with: #{msg}"
end
def do_something_with(arg)
puts arg
end
do_something_with 'foo' or die 'unknown error'
# >> foo
# >> Exited with: unknown error
由于ruby parsing rules (pseudo-BNF),or
可以很好地使用ruby的可选括号。
简而言之,参数列表(CALL_ARGS)是ARG的列表,以逗号分隔。现在,大多数东西都是ARG(类定义,例如,通过作为PRIMARY),但不是简单的EXPR。如果用括号括起表达式,那么它将匹配"复合语句"的规则。因此,将是一个主要的ARG。这意味着什么
puts( (nil or 4) ) # will work, compound statement as first argument
puts (nil or 4) # same as above, omitted optional method call parentheses
puts(nil or 4) # will not work, EXPR can't be an argument
puts nil or 4 # will work as `puts(nil) or 4`
您可以阅读上面引用的语法,以了解完全它是如何工作的。
puts class Foo
def bar
puts "hello"
end
end, 'second argument'
# >> bar # this is the "value" of the class definition
# >> second argument
答案 1 :(得分:10)
这是因为or
和and
的优先级低于方法调用。您的表达式被解释为:
{puts(nil} or {4)}
其中{}
代表分组。语法错误来自表达式
puts(nil
(以下也会引发语法错误):
4)
如果你通过在表达式周围放一对括号来强制分组,那么它将按照你想要的方式工作:
puts((nil or 4))
请注意,外部括号对用于方法调用,而不是分组,因此只有一对括号无法更改分组。
或者,如果您通过放置空格来消除用于分组的一对括号的歧义,那么这也将起作用:
puts (nil or 4)
答案 2 :(得分:7)
Ruby允许我们在函数调用中删除括号。也就是说,而不是:
func1(ARG, ARG, ARG) or func2(ARG, ARG, ARG)
我们可以这样做:
func1 ARG, ARG, ARG or func2 ARG, ARG, ARG
但是,为了使最后一行的行为类似于第一行,“或”不能是ARG顶层使用的运算符(否则最后一行将被解释为func1(ARG, ARG, ARG or func2 ARG, ARG, ARG)
)。实际上,当我们查看BNF时,我们看到ARG没有直接提及“或”/“和”(这意味着它在那里是非法的)。
但ARG仍然可以使用“或”:将表达式包装在括号中。在BNF中,我们将此视为ARG可以分支的PRIMARY替代方案(作为PRIMARY,反过来,分支到'(' COMPSTMT ')'
)。
func (1 or 2)
和func((1 or 2))
有效,而func(1 or 2)
没有: func(1 or 2)
是BNF调用的FUNCTION,它扩展为OPERATION ['(' [CALL_ARGS] ')']
,这意味着ARG为“1或2”,但正如我们所见,ARG不能包含“或”,因此无效。
func((1 or 2))
又是OPERATION ['(' [CALL_ARGS] ')']
,但此处的ARG是“(1或2)”,这是有效的 ARG(请参阅PRIMARY如上所述)。
func (1 or 2)
是BNF调用COMMAND的内容,它扩展为OPERATION CALL_ARGS
,这意味着ARG为“(1或2)”,这是有效 ARG(见上文提到的PRIMARY)。