为什么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在解析器级别识别局部变量.这就是文档说的原因:(强调添加)
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c# – 为什么我的Catch块只在Visual Studio中调试时运行?
- swift – 如何获取其rawType为Int 的枚举的字符串大小写
- c# – 在SignalR lib中使用SignalR 2.0 Owin管道
- vb.net 关闭所有已经打开的窗体 包括启动窗体
- objective-c – 排序NSDictionary按存储为value的对象的属性
- 09-Oracle入门之多表查询
- ruby – Capybara-webkit,rspec集成规范和xvfb:webkit_ser
- macos – 滚动时NSTableView非常迟缓
- ruby-on-rails – Rails不会在生产中提供静态文件
- oracle dba 应该熟悉的命令