2

我如何预测 Ruby 将如何解析事物?

在尝试连接字符串时,我在 Ruby 中遇到了一个非常令人惊讶的解析错误。

> "every".capitalize +"thing"
=> NoMethodError: undefined method `+@' for "thing":String

当然,如果你把额外的空间放在它们里面,它就会按预期工作;

> "every".capitalize + "thing"
=> "Everything"

如果我有anything.any_method +"any string". Ruby 所做的是假设我们已经省略了括号,并试图为该方法提供一个参数;

"every".capitalize( +"thing" )

它注意到我们没有+@在字符串上定义一元运算符,并抛出该错误。

我的问题是,我应该使用什么原则来预测 Ruby 解析器的行为?经过大量的谷歌搜索后,我才发现了这个错误。值得注意的是,.capitalize它从来不带参数(甚至在 C 源代码中也不带参数)。如果您使用不适用于前一个对象的方法,它仍然会抛出+@错误而不是undefined method 'capitalize' for "every":String错误。所以这个解析显然是高级别的。我没有足够的知识阅读 Matz 的parser.y。我遇到了其他类似的令人惊讶的错误。谁能告诉我Ruby的解析优先级?

4

1 回答 1

3

如果你想看看 ruby​​ 是如何解析你的代码的,你可以转储分析树,即

ruby -e '"every".capitalize +"thing"' --dump parsetree

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_CALL (line: 1)
#     +- nd_mid: :capitalize
#     +- nd_recv:
#     |   @ NODE_STR (line: 1)
#     |   +- nd_lit: "every"
#     +- nd_args:
#         @ NODE_ARRAY (line: 1)
#         +- nd_alen: 1
#         +- nd_head:
#         |   @ NODE_CALL (line: 1)
#         |   +- nd_mid: :+@
#         |   +- nd_recv:
#         |   |   @ NODE_STR (line: 1)
#         |   |   +- nd_lit: "thing"
#         |   +- nd_args:
#         |       (null node)
#         +- nd_next:
#             (null node)

我有时也喜欢使用explainruby,因为它对我来说更容易:)

于 2013-06-24T22:09:23.580 回答