当我执行:
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)
。)当我执行:
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)
。)因为这是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 中,or
可以很好地与可选括号配合使用,这是由于 Ruby 的解析规则(伪BNF)。
简而言之,参数列表(CALL_ARGS)是由逗号分隔的 ARG 列表。现在,大多数任何东西都是 ARG(例如,通过是 PRIMARY 的类定义),但不是未装饰的 EXPR。如果您用括号括起来一个表达式,那么它将匹配“复合语句”的规则,因此将成为 PRIMARY,这是一个 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
这是因为or
和and
比方法调用的优先级更低。你的表达式被解释为:
{puts(nil} or {4)}
{}
代表分组。语法错误来自于表达式。
puts(nil
(而且以下内容也会引发语法错误):
4)
如果你通过在表达式周围加上一对括号来强制分组,则它将按照你预期的方式工作: 如果你通过在表达式周围加上一对括号来强制分组,则它将按照你预期的方式工作:
puts((nil or 4))
请注意,最外层的括号用于方法调用而不是分组,因此仅有一对括号并不会改变分组。
另一种方法是,如果你在一对括号中间添加一个空格以明确表示它是用于分组的,则也可以起到相同的作用:
puts (nil or 4)
@Sergio Tulentsev(和@sawa)提供了一个很好的答案,但我想重新表述一下,以便将来我能快速理解:
Ruby允许我们在函数调用中省略括号。也就是说,不需要写成:
func1(ARG, ARG, ARG) or func2(ARG, ARG, ARG)
func1 ARG, ARG, ARG or func2 ARG, ARG, ARG
func1(ARG, ARG, ARG or func2 ARG, ARG, ARG)
)。实际上,当我们查看BNF时,我们发现ARG没有直接提到“or”/“and”(这意味着在此处使用是非法的)。'(' COMPSTMT ')'
)。func (1 or 2)
和func((1 or 2))
有效,而func(1 or 2)
无效:func(1 or 2)
是BNF中称为FUNCTION的部分,它扩展为OPERATION ['(' [CALL_ARGS] ')']
,这意味着ARG是“1 or 2”,但正如我们所见,ARG不能包含“or”,因此是无效的。
- func((1 or 2))
也是OPERATION ['(' [CALL_ARGS] ')']
,但这里ARG是“(1 or 2)”,这是一个有效的ARG(参见上面提到的PRIMARY)。
- func (1 or 2)
是BNF中称为COMMAND的部分,它扩展为OPERATION CALL_ARGS
,这意味着ARG是“(1 or 2)”,这是一个有效的ARG(参见上面提到的PRIMARY)。
puts (nil or 4)
可以正常运行 - 在put
后加了一个空格。 - Wand Makerputs((nil or 4))
也能工作?! - Dave Schweisguth