Ruby on Rails – Ruby运算符优先级 – 括号

以下代码导致错误

例1

if params[:id] == '2' || params.has_key? :id abort('params id = 2 or nothing') end syntax error, unexpected tSYMBEG, expecting keyword_then or ';' or '\n' if params[:id] == '2' || params.has_key? :id 

但是,切换条件语句|| 添加括号可以100%工作。

例2

 if params.has_key? :id || params[:id] == '2' abort('params id = 2 or nothing') end 

例3

 if (params[:id] == '2') || (params.has_key? :id) abort('params id = 2 or nothing') end 

任何人都可以向我解释为什么示例1会导致错误?

谢谢

你的问题发生在:

 params[:id] == '2' || params.has_key? :id 

可以简化为:

 :foo || some_method :bar 

这会导致同样的错误。 这个表达原则上是模糊的

 (:foo || some_method) :bar (1) 

 :foo || (some_method :bar) (2) 

当表达式不明确时,它会被其他因素解决。 一个因素,运算符优先级在这里没有说明消除(1)和(2)之间的歧义。 下一个因素是线性顺序。 自|| 出现在有问题的表达式中的参数application () (省略)之前,前者适用于后者。 因此,表达式被解释为(1)。 由于(:foo || some_method)将被解析为表达式,因此会有两个表达式彼此相邻。 这是不合语法的,就像:

 :baz :bar 

是不合语法的。

实际上,如果您将订单切换为:

 some_method :bar || :foo 

然后,它将被解释为

 (some_method :bar) || :foo 

出于同样的原因,语法错误将消失。

此外,当您通过显式使用括号来指示参数应用程序来解决歧义时:

 :foo || some_method(:bar) 

然后没有需要解决的歧义,语法错误消失了。

你的:id是Ruby中的一个符号。

 a = {'id' => 'a', 'value' => 'value'} a.has_key? 'id' => true a.has_key? :id => false 

所以你需要改变你的代码:

 if params[:id] == '2' or params.has_key? 'id' abort('params id = 2 or nothing') end 

注意:如果要在检查值之前使用此代码检查密钥更有意义。

注2:经测试:

 params = {'id' => 'a', 'value' => 'value'} if params[:id] == '2' or params.has_key? 'id' abort('params id = 2 or nothing') end 

和Ruby 2.0.0

另请查看此问题以获取有关Ruby符号的更多信息。

它与Ruby如何评估if语句有关。

例1就像if (params[:id] == '2' || params.has_key?) :id

这可以解决意外的符号错误,因为您可以看到syntax error, unexpected tSYMBEG

正如家伙所说……解析器不假设该符号是has_key的参数? 方法

您可以通过显式编写括号来绕过错误

 if params[:id] == '2' || params.has_key?(:id)