当我做:
puts(nil or 4)
Run Code Online (Sandbox Code Playgroud)
Ruby抱怨:
SyntaxError: syntax error, unexpected keyword_or, expecting ')'
Run Code Online (Sandbox Code Playgroud)
这是为什么?puts(nil || 4)
确实有效,但我想知道为什么or
不这样做.我认为两者之间的区别只在于它们的运算符优先级.
(我知道这个表达nil or 4
似乎没有用,因为它总是会返回4
.这只是一个例子,为了简单起见.我的实际表达是Integer(ENV['WD'] or 4)
.)
Ser*_*sev 15
因为这是ruby语法的方式.
and
/ or
keywords被设计用于控制流构造.考虑这个例子:
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
Run Code Online (Sandbox Code Playgroud)
or
由于ruby 解析规则(伪BNF),这里可以很好地使用ruby的可选括号.
简而言之,参数列表(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`
Run Code Online (Sandbox Code Playgroud)
您可以阅读上面引用的语法,以准确了解它的工作原理.
puts class Foo
def bar
puts "hello"
end
end, 'second argument'
# >> bar # this is the "value" of the class definition
# >> second argument
Run Code Online (Sandbox Code Playgroud)
saw*_*awa 10
这是因为or
并且and
具有比方法调用更低的优先级.您的表达式被解释为:
{puts(nil} or {4)}
Run Code Online (Sandbox Code Playgroud)
在哪里{}
代表分组.语法错误来自表达式
puts(nil
Run Code Online (Sandbox Code Playgroud)
(以下也会引发语法错误):
4)
Run Code Online (Sandbox Code Playgroud)
如果通过在表达式周围放置一对括号来强制分组,那么它将按照您的预期方式工作:
puts((nil or 4))
Run Code Online (Sandbox Code Playgroud)
请注意,外部括号对用于方法调用,而不是分组,因此只有一对括号无法更改分组.
或者,如果您通过放置空格来消除用于分组的一对括号的歧义,那么这也将起作用:
puts (nil or 4)
Run Code Online (Sandbox Code Playgroud)
@Sergio Tulentsev(和@sawa)给出了一个很好的答案,但我想改写它,以便我将来能够快速理解它:
Ruby允许我们在函数调用中删除括号.也就是说,而不是:
func1(ARG, ARG, ARG) or func2(ARG, ARG, ARG)
Run Code Online (Sandbox Code Playgroud)
我们可以做的:
func1 ARG, ARG, ARG or func2 ARG, ARG, ARG
Run Code Online (Sandbox Code Playgroud)
但是,为了使最后一行的行为类似于第一行,"或"不能是在ARG的顶层使用的运算符(否则最后一行将被解释为func1(ARG, ARG, ARG or func2 ARG, ARG, ARG)
).实际上,当我们查看BNF时,我们看到ARG没有直接提及"或"/"和"(这意味着它在那里是非法的).
但ARG仍然可以使用"或":将表达式包装在括号中.在BNF中,我们将此视为ARG可以分支的主要替代方案(作为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).
归档时间: |
|
查看次数: |
733 次 |
最近记录: |