2

以下代码导致错误

示例 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

4 回答 4

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)

那么就没有歧义需要解决了,语法错误就消失了。

于 2013-07-18T10:46:29.557 回答
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

和红宝石 2.0.0

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

于 2013-07-18T10:37:20.280 回答
0

As guy says... the parser doesn't assume that the symbol is a parameter for the has_key? method

You can bypass the error by explicitly coding the parentheses

if params[:id] == '2' || params.has_key?(:id)
于 2013-07-18T10:15:44.727 回答
0

它与如何Ruby评估该if陈述有关。

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

如您所见,它解决了意外的符号错误syntax error, unexpected tSYMBEG

于 2013-07-18T10:03:25.377 回答