saw*_*awa 6 ruby parsing local-variables variable-assignment guard-clause
我正在NameError: undefined local variable or method使用ruby 2.1.2
正如在这个问题中观察到的,表达式如:
bar if bar = true
Run Code Online (Sandbox Code Playgroud)
引发未定义的局部变量错误(前提bar是未定义),因为bar解析器在分配之前会读取它.而且我相信这个表达方式与以前没什么区别:
bar if bar = false
Run Code Online (Sandbox Code Playgroud)
两者之间的区别在于主体是否被评估,但是如果遇到未定义的局部变量,则在评估条件之前立即引发错误并不重要.
但是当我在Ruby 2.1.2上运行第二个代码时,它不会引发错误.它之前是这样吗?如果是这样,那么解析讨论的内容是什么?如果没有,Ruby规范是否已更改?有没有提到这个?它在1.8.7,1.9.3等中做了什么?
是否bar定义没有区别。在这两种情况下,bar在体内都是未定义的。但是,在后一种情况下,永远不会评估主体,因此没关系。您永远不会解析名称bar,因此在名称解析期间永远不会出错。
解析分配时定义局部变量。它们在执行分配时被初始化。
变量被单数化是完全好的。nil在这种情况下,它将评估为:
if false
bar = 42
end
bar
# => nil
Run Code Online (Sandbox Code Playgroud)
但是,如果变量未定义,则Ruby不知道裸字是局部变量还是无接收器的无参数消息发送:
foo
# NameError: undefined local variable or method `foo'
# ^^^^^^^^^
# Ruby doesn't know whether it's a variable or a message send
Run Code Online (Sandbox Code Playgroud)
与之比较:
foo()
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^
self.foo
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
现在都在一起了:
foo()
# NoMethodError: undefined method `foo'
self.foo
# NoMethodError: undefined method `foo'
foo
# NameError: undefined local variable or method `foo'
if false
foo = 42
end
foo
# => nil
foo = :fortytwo
foo
# => :fortytwo
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下的麻烦在于,解析表达式的顺序(以及因此定义变量的顺序)与执行表达式的顺序不匹配。
分配执行第一,你认为这会使得该bar会在体内进行定义。但这不是,因为首先对主体进行了解析,因此在看到分配之前,我不知道这是方法还是变量节点插入了语法树中。
但是,如果从未解释该节点,即条件为假,则不会发生任何不良情况。
在1.8.7、 、中1.9.3,2.0.0甚至2.1.1我收到 2 个警告,但没有错误:
2.0.0-p247 :007 > bar if bar = false
(irb):7: warning: found = in conditional, should be ==
=> nil
2.0.0-p247 :008 > bar if bar = true
(irb):8: warning: found = in conditional, should be ==
=> true
Run Code Online (Sandbox Code Playgroud)
而在2.1.2你提到的版本中我收到 2 个警告和 1 个NameError错误。
2.1.2 :001 > bar if bar = true
(irb):1: warning: found = in conditional, should be ==
NameError: undefined local variable or method `bar' for main:Object
from (irb):1
from /home/durrantm/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :002 > bar if bar = false
(irb):2: warning: found = in conditional, should be ==
=> nil
Run Code Online (Sandbox Code Playgroud)
这是在我的 Ubuntu 14 上
| 归档时间: |
|
| 查看次数: |
233 次 |
| 最近记录: |