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

时间:2013-07-18 09:52:30

标签: ruby-on-rails ruby ruby-on-rails-3

以下代码会导致错误

示例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会导致错误吗?

由于

4 个答案:

答案 0 :(得分:4)

您的问题发生在:

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

可以简化为:

:foo || some_method :bar

导致相同的错误。

之间原则上这个表达式是不明确的
(:foo || some_method) :bar         (1)

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

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

:baz :bar

是不合语法的。

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

some_method :bar || :foo

然后,它将被解释为

(some_method :bar) || :foo

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

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

:foo || some_method(:bar)

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

答案 1 :(得分:1)

您的: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

另请查看this question以获取有关Ruby符号的更多信息。

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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

您可以通过明确编写括号

来绕过错误
if params[:id] == '2' || params.has_key?(:id)