gpt4 book ai didi

ruby - 为什么像 1 + n *= 3 这样的语句在 Ruby 中是允许的?

转载 作者:数据小太阳 更新时间:2023-10-29 06:29:39 25 4
gpt4 key购买 nike

许多 Ruby 文档中的优先级表列出了二进制算术运算的优先级高于其相应的复合赋值运算符。这让我相信像这样的代码不应该是有效的 Ruby 代码,但它确实是。

1 + age *= 2

如果优先规则是正确的,我希望上面的代码会像这样用括号括起来:
((1 + age) *= 2) #ERROR: Doesn't compile

但事实并非如此。

那么什么给呢?

最佳答案

正在检查 ruby -y输出,您可以确切地看到正在发生的事情。鉴于1 + age *= 2的来源,输出表明会发生这种情况(简化):
tINTEGER找到,识别为 simple_numeric ,这是一个 numeric ,这是一个 literal ,这是一个 primary .知乎+接下来,primary被识别为 arg .
+成立。还不能成交。
tIDENTIFIER成立。知道下一个 token 是 tOP_ASGN (运算符(operator)分配),tIDENTIFIER被识别为 user_variable ,然后作为 var_lhs .
tOP_ASGN成立。还不能成交。
tINTEGER成立。和上一个一样,最终识别为primary .知道下一个 token 是 \n , primary被识别为 arg .

此时我们有arg + var_lhs tOP_ASGN arg在堆栈上。在此背景下,我们承认最后一个 argarg_rhs .我们现在可以弹出 var_lhs tOP_ASGN arg_rhs从堆栈中并将其识别为 arg , 堆栈以 arg + arg 结尾,可以简化为 arg .
arg然后被识别为 expr , stmt , top_stmt , top_stmts . \n被识别为 term ,然后 terms ,然后 opt_terms . top_stmts opt_terms被识别为 top_compstmt ,最终 program .

另一方面,给定来源 1 + age * 2 , 有时候是这样的:
tINTEGER找到,识别为 simple_numeric ,这是一个 numeric ,这是一个 literal ,这是一个 primary .知乎+接下来,primary被识别为 arg .
+成立。还不能成交。
tIDENTIFIER成立。知道下一个 token 是 * , tIDENTIFIER被识别为 user_variable ,然后 var_ref ,然后 primary , 和 arg .
*成立。还不能成交。
tINTEGER成立。和上一个一样,最终识别为primary .知道下一个 token 是 \n , primary被识别为 arg .

堆栈现在是 arg + arg * arg . arg * arg可以减少到arg ,结果 arg + arg也可以减少到arg .
arg然后被识别为 expr , stmt , top_stmt , top_stmts . \n被识别为 term ,然后 terms ,然后 opt_terms . top_stmts opt_terms被识别为 top_compstmt ,最终 program .

关键区别是什么?在第一段代码中,age (a tIDENTIFIER) 被识别为 var_lhs (作业的左侧),但在第二个中,它是 var_ref (变量引用)。为什么?因为 Bison 是一个 LALR(1) 解析器,这意味着它具有单 token 前瞻。所以agevar_lhs因为 Ruby 看到了 tOP_ASGN接下来;它是 var_ref当它看到* .这是因为 Ruby 知道(使用 Bison 生成的巨大 state transition table)一个特定的产生是不可能的。具体来说,此时栈为arg + tIDENTIFIER ,下一个标记是 *= .如 tIDENTIFIER被识别为 var_ref (这导致 arg )和 arg + arg减少到 arg ,则没有以 arg tOP_ASGN 开头的规则;因此,tIDENTIFIER不允许成为var_ref ,然后我们看下一个匹配规则(var_lhs 一个)。

所以 Aleksei 是部分正确的,因为“当它看到语法错误时,它会尝试另一种方式”是有道理的,但它仅限于 future 的一个标记,而“尝试”只是在状态表中查找。 Ruby 无法执行我们人类用来理解诸如 "the horse raced past the barn fell" 之类的句子的复杂修复策略。 ,我们很高兴地解析到最后一个单词,然后在第一个解析结果不可能时重新评估整个句子。

tl;dr:优先表不完全正确。 Ruby 源代码中没有它存在的地方;相反,它是各种解析规则相互作用的结果。当引入赋值的左侧时,许多优先级规则就会失效。

关于ruby - 为什么像 1 + n *= 3 这样的语句在 Ruby 中是允许的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57654434/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com