简体   繁体   English

NameError:undefined - 在Ruby 2.1.2中更改了局部变量的解析规则吗?

[英]NameError: undefined - have parsing rules for local variables changed in Ruby 2.1.2?

I am getting NameError: undefined local variable or method with ruby 2.1.2 我得到NameError: undefined local variable or method使用ruby 2.1.2的NameError: undefined local variable or method

As observed in this question , expressions like: 正如在这个问题中观察到的,表达式如:

bar if bar = true

raises an undefined local variable error (provided that bar is not defined prior) because bar is read by the parser before it is assigned. 引发未定义的局部变量错误(假设事先未定义bar ),因为解析器在分配之前会读取bar And I believe that there used to be no difference with that with this expression: 而且我相信这个表达方式与以前没什么区别:

bar if bar = false

The difference between the two is whether the main body is evaluated or not, but that should not matter if encountering an undefined local variable immediately raises an error before evaluating the condition. 两者之间的区别在于主体是否被评估,但是如果遇到未定义的局部变量,则在评估条件之前立即引发错误并不重要。

But when I run the second code on Ruby 2.1.2, it does not raise an error. 但是当我在Ruby 2.1.2上运行第二个代码时,它不会引发错误。 Has it been like that from before? 它之前是这样吗? If so, then what was the parsing discussion all about? 如果是这样,那么解析讨论的内容是什么? If not, has Ruby specification changed? 如果没有,Ruby规范是否已更改? Is there any reference to that? 有没有提到这个? What did it do in 1.8.7, 1.9.3, etc. ? 它在1.8.7,1.9.3等中做了什么?

There is no difference with regards to whether bar is defined or not. 关于是否定义bar没有区别。 In both cases, bar is undefined in the body. 在这两种情况下, bar都是未定义的。 However, in the latter case, the body is never evaluated, therefore it doesn't matter. 然而,在后一种情况下,身体永远不会被评估,因此无关紧要。 You never resolve the name bar , therefore you never get an error during name resolution. 您永远不会解析名称bar ,因此在名称解析期间永远不会出现错误。

Local variables are defined when an assignment is parsed . 解析赋值时定义局部变量。 They are initialized when an assignment is executed . 它们在执行赋值时初始化

It's perfectly fine for a variable to be unitialized. 对变量进行单位化是完全正确的。 It will just evaluate to nil in that case: 在这种情况下,它只会评估nil

if false
  bar = 42
end

bar
# => nil

However, if the variable is undefined , then Ruby doesn't know whether a bare word is a local variable or a receiverless argumentless message send: 但是,如果变量未定义 ,则Ruby不知道裸字是局部变量还是无接收器无参数消息发送:

foo
# NameError: undefined local variable or method `foo'
#                                     ^^^^^^^^^
# Ruby doesn't know whether it's a variable or a message send

Compare with: 与之比较:

foo()
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^

self.foo
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^

All together now: 现在都在一起了:

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

The trouble in this particular case is that the order in which the expressions are parsed (and thus the order in which variables are defined) does not match with the order in which the expressions are executed . 在这种特殊情况下的问题是表达式被解析的顺序(以及因此定义变量的顺序)与表达式的执行顺序匹配。

The assignment is executed first , which would make you assume that bar would be defined in the body. 首先执行赋值,这将使您假设将在正文中定义bar But it isn't, because the body was parsed first and thus an I don't know whether this is a method or a variable node was inserted into the syntax tree before the assignment was ever seen. 但事实并非如此,因为首先解析了主体,因此我不知道这是一个方法,还是 看到赋值之前变量节点插入到语法树中。

However, if that node is never interpreted, ie the condition is false, then nothing bad will happen. 但是,如果永远不解释该节点,即条件为假,则不会发生任何不良情况。

My answer is based on Ruby 2.1.2 . 我的回答是基于Ruby 2.1.2

Adding with @Jörg W Mittag answer . 添加@JörgWMittag 答案

Another commonly confusing case is when using a modifier if : 另一个常见的令人困惑的情况是在使用修饰符if

p a if a = 0.zero? # => NameError: undefined local variable or method `a'

Rather than printing “true” you receive a NameError, “undefined local variable or method `a'”. 您不会打印“true”而是收到NameError,“未定义的局部变量或方法”a“”。 Since ruby parses the bare a left of the if first and has not yet seen an assignment to a it assumes you wish to call a method. 因为ruby解析了if的左边,并且还没有看到对它的赋值,假定你想调用一个方法。 Ruby then sees the assignment to a and will assume you are referencing a local method. 然后Ruby看到对a的赋值,并假设您正在引用本地方法。

The confusion comes from the out-of-order execution of the expression. 混淆来自表达式out-of-order执行。 First the local variable is assigned-to then you attempt to call a nonexistent method. 首先分配局部变量,然后尝试调用不存在的方法。

Based on above explanation - 基于以上解释 -

bar if bar = false

simply returns nil , as the expression has been evaluated as false , the body of the code associated with the if modifier wouldn't be executed. 简单地返回nil ,因为表达式已被评估false ,因此不会执行与if修饰符关联的代码的主体。 nil is being returned by any block in Ruby, by default when there is no explicit default value. 默认情况下,当没有显式默认值时 ,Ruby中的任何都返回nil

Yes it changed in ruby 2.1.2 是的,它在红宝石2.1.2中有所改变

In 1.8.7 , 1.9.3 , 2.0.0 and even 2.1.1 I get 2 warnings and no errors: 1.8.71.9.32.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 

whereas in the 2.1.2 version you mention I get 2 warnings and 1 NameError error. 而在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 

This is on my Ubuntu 14 这是在我的Ubuntu 14上

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 主对象的未定义局部变量或方法:对象 <NameError> 对于Ruby - undefined local variables or method for main: Object <NameError> For Ruby NameError-未定义的局部变量-将数组从ruby文件解析为haml文件 - NameError - undefined local variable - Parsing array from ruby file to haml file 定义了一个Ruby NameError,未定义的局部变量 - A Ruby NameError, undefined local variable, was defined Ruby:未定义的局部变量(NameError)-但已定义 - Ruby: undefined local variable (NameError) — but it is defined Ruby NameError未定义的局部变量或方法`e - Ruby NameError undefined local variable or method `e Ruby NameError:未定义的局部变量或方法“ r” - Ruby NameError: undefined local variable or method `r' for Ruby:未定义的局部变量或方法&#39;n1&#39;(NameError) - Ruby :undefined local variable or method `n1' (NameError) Ruby on Rails NameError:未定义的局部变量或方法“记录” - ruby on rails NameError: undefined local variable or method 'record' 使用ruby2.1.2的未初始化常量Yaml(NameError) - uninitialized constant Yaml (NameError) using ruby2.1.2 Ruby Gems每个命令上的“ NameError:main:Object的未定义局部变量或方法&#39;update&#39;” - Ruby Gems “NameError: undefined local variable or method 'update' for main:Object” on every command
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM