【问题标题】:Why is a = b rescue stmt an error but stmt rescue stmt is not?为什么 a = b rescue stmt 是错误而 stmt rescue stmt 不是?
【发布时间】:2013-02-27 16:43:56
【问题描述】:

我无法确定以下 ruby​​ 内联救援代码有什么问题

def test_check()
p  "first st"
t = 5 * lsdj rescue return false
p "second"
end

p test_check

这是一条错误消息syntax error, unexpected kFALSE, expecting kEND 但如果我删除赋值语句,它会正常工作(返回 false)。

 def test_check()
    p  "first st"
     5 * lsdj rescue return false
    p "second"
    end

如果出现问题,ruby 中内联救援的正确语法是什么。

【问题讨论】:

  • +1。一个非常好的问题。人们会期望修饰符规则在这两种情况下解析相同,而这个问题的答案涉及到很多关于为什么 Ruby 是这样的问题。也许只有 Matz 知道完整的答案,但我在下面贡献了我对它的理解。

标签: ruby syntax syntax-error


【解决方案1】:

内联rescue 在赋值中使用时不会将语句作为参数1,2 -- 它只需要表达式的值获救。

但要小心,你认为这会返回什么?

def q
  return 5 * lsdj rescue false
  true
end

不是false,它返回true。改为这样做,这样救援只适用于表达式。

def q
  return (5 * lsdj rescue false)
  true
end

这个返回false。


注意事项。
1.这实际上是一个非常好的问题。重述:
      为什么是 a = b rescue stmt 一个错误,但是 stmt rescue stmt 是不是吗?
表面上的答案是,在赋值情况下,rhs 和救援语句在 ruby​​ 语法中是 arg 非终结符而不是完整语句,而在语句情况下语法只是在救援后解析完整的 stmt 规则。这只是它的定义方式。现在,如果你接着问为什么会这样? ...嗯... Ruby 的复杂语法处于 yacc(1) 能力的边缘。在我看来,在许多情况下,Matz 详细说明了在某些情况下会接受什么,而不是仅仅使用像 expr 这样的单个非终结符,我想原因是为了保持语法 LALR(1) 并将不可避免的shift/reduce conflicts 限制在可容忍的范围内。 Check out parse.y 在 Ruby 源代码分发版中进行有趣的阅读。
2。这是一个示例:def q; (t = 5 * lsdj) rescue return false; true; end
这可以按您的意愿工作,因为它恰好与其他语法规则匹配。我听说有些限制是为了支持诗歌模式而存在的。

【讨论】:

  • 我搜索了很多文档,但找不到任何好的文档。最后给出了很好的解释,感谢@DigitalRoss。
【解决方案2】:

您的代码将被解释为:

def test_check()
p  "first st"
t = (5 * lsdj rescue return) false
p "second"
end

这使得false 处于无效位置。为了修复它,请加上括号:

def test_check()
p  "first st"
t = 5 * lsdj rescue (return false)
p "second"
end

【讨论】:

  • 为了迂腐,具体问题是救援修饰符的参数(当应用于赋值时)是非终结符 arg 并且根本不解析以 @ 开头的语句987654325@ 但是,添加 (...) 会导致语法解析 primary 表达式,而它恰好包含 return 语句。
猜你喜欢
  • 1970-01-01
  • 2013-11-01
  • 2017-10-08
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
相关资源
最近更新 更多