Ruby   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了为什么Ruby在抛出NameError异常后会保留代码评估?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我无法向自己解释的简单代码:
puts a if a = 1

这导致了

warning: found = in conditional,should be ==
NameError: undefined local variable or method 'a' for main:Object

然,现在检查我们可以看到,它已被定义:

a #=> 1

尽管抛出了异常,为什么将其分配给1?

docs

这部分仍然令人困惑 – 为什么解释器没有检测到已经定义的局部变量a并仍然试图调用“不存在”的方法?如果它也不检查局部变量,找到定义的局部变量a并打印1?

解决方法

让我们来看看Ruby的修饰符的抽象语法树,如果:
$ruby --dump=parsetree -e 'puts a if a = 1'

# @ NODE_SCOPE (line: 1,code_range: (1,0)-(1,15))
# +- nd_tbl: :a
# +- nd_args:
# |   (null nodE)
# +- nd_body:
#     @ NODE_PRELUDE (line: 1,15))
#     +- nd_head:
#     |   (null nodE)
#     +- nd_body:
#     |   @ NODE_IF (line: 1,15))
#     |   +- nd_cond:
#     |   |   @ NODE_DASGN_CURR (line: 1,10)-(1,15))
#     |   |   +- nd_vid: :a
#     |   |   +- nd_value:
#     |   |       @ NODE_LIT (line: 1,14)-(1,15))
#     |   |       +- nd_lit: 1
#     |   +- nd_body:
#     |   |   @ NODE_FCALL (line: 1,6))
#     |   |   +- nd_mid: :puts
#     |   |   +- nd_args:
#     |   |       @ NODE_ARRAY (line: 1,5)-(1,6))
#     |   |       +- nd_alen: 1
#     |   |       +- nd_head:
#     |   |       |   @ NODE_VCALL (line: 1,6))
#     |   |       |   +- nd_mid: :a
#     |   |       +- nd_next:
#     |   |           (null nodE)
#     |   +- nd_else:
#     |       (null nodE)
#     +- nd_compile_option:
#         +- coverage_enabled: false

对于标准如果:

$ruby --dump=parsetree -e 'if a = 1 then puts a end'

# @ NODE_SCOPE (line: 1,24))
# +- nd_tbl: :a
# +- nd_args:
# |   (null nodE)
# +- nd_body:
#     @ NODE_PRELUDE (line: 1,24))
#     +- nd_head:
#     |   (null nodE)
#     +- nd_body:
#     |   @ NODE_IF (line: 1,24))
#     |   +- nd_cond:
#     |   |   @ NODE_DASGN_CURR (line: 1,3)-(1,8))
#     |   |   +- nd_vid: :a
#     |   |   +- nd_value:
#     |   |       @ NODE_LIT (line: 1,7)-(1,8))
#     |   |       +- nd_lit: 1
#     |   +- nd_body:
#     |   |   @ NODE_FCALL (line: 1,20))
#     |   |   +- nd_mid: :puts
#     |   |   +- nd_args:
#     |   |       @ NODE_ARRAY (line: 1,19)-(1,20))
#     |   |       +- nd_alen: 1
#     |   |       +- nd_head:
#     |   |       |   @ NODE_DVAR (line: 1,20))
#     |   |       |   +- nd_vid: :a
#     |   |       +- nd_next:
#     |   |           (null nodE)
#     |   +- nd_else:
#     |       (null nodE)
#     +- nd_compile_option:
#         +- coverage_enabled: false

唯一的区别是puts的方法参数

#     |   |       |   @ NODE_VCALL (line: 1,6))
#     |   |       |   +- nd_mid: :a

VS:

#     |   |       |   @ NODE_DVAR (line: 1,20))
#     |   |       |   +- nd_vid: :a

使用修饰符if,解析器将a视为方法调用并创建NODE_VCALl.这指示解释器进行方法调用(尽管存在局部变量a),从而产生NameError. (因为没有方法a)

使用标准if,解析器将a视为局部变量并创建NODE_DVAR.这指示解释器查找按预期工作的局部变量.

如您所见,Ruby在解析器级别识别局部变量.这就是文档说的原因:(强调添加)

大佬总结

以上是大佬教程为你收集整理的为什么Ruby在抛出NameError异常后会保留代码评估?全部内容,希望文章能够帮你解决为什么Ruby在抛出NameError异常后会保留代码评估?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。