Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 与falsy`if`块中的赋值操作混淆_Ruby_If Statement_Nameerror - Fatal编程技术网

Ruby 与falsy`if`块中的赋值操作混淆

Ruby 与falsy`if`块中的赋值操作混淆,ruby,if-statement,nameerror,Ruby,If Statement,Nameerror,我在if块中玩赋值操作,发现了以下结果,这让我很惊讶: C:\>irb --simple-prompt if false x = 10 end #=> nil p x nil x.object_id #=> 4 #=> nil p y NameError: undefined local variable or method `y' for main:Object from (irb):5 from C:/Ruby193/bin/irb:1

我在
if
块中玩赋值操作,发现了以下结果,这让我很惊讶:

C:\>irb --simple-prompt
if false
x = 10
end
#=> nil
p x
nil
x.object_id
#=> 4
#=> nil
p y
NameError: undefined local variable or method `y' for main:Object
        from (irb):5
        from C:/Ruby193/bin/irb:12:in `<main>'
成功案例:

class Foo
  def self.show
    @@X = 10 if true
    p @@X,"hi",@@X.object_id
  end
end
#=> nil
Foo.show
10
"hi"
4
#=> [10, "hi", 4]
Ruby具有局部变量“highting”。如果在方法中的任何位置都有对局部变量的赋值,则该变量在方法中的任何位置都存在,即使在赋值之前,即使赋值从未实际执行。在分配变量之前,它的值为
nil

编辑:


上述说法并不完全正确。Ruby确实有一种变量提升的形式,当存在局部变量赋值但未执行时,它将定义一个局部变量。但是,在上述方法中发生赋值的地方找不到定义变量的地方。

Ruby始终解析所有代码。它不会将false视为不解析内部内容的标志,它会对其进行求值,并看到内部代码不应该在Ruby中执行,局部变量在解析器首次遇到赋值时由解析器定义,然后从那时起就在范围内

下面是一个小演示:

foo # NameError: undefined local variable or method `foo' for main:Object

if false
  foo = 42
end

foo # => nil
如您所见,即使第4行上的赋值从未执行,第7行上仍然存在局部变量。然而,它被解析了,这就是局部变量
foo
存在的原因。但由于从未执行赋值,因此变量未初始化,因此计算结果为
nil
,而不是
42

在Ruby中,大多数未初始化甚至不存在的变量的计算结果为
nil
。对于局部变量、实例变量和全局变量,这是正确的:

defined? foo       #=> nil
local_variables    #=> []
if false
  foo = 42
end
defined? foo       #=> 'local-variable'
local_variables    #=> [:foo]
foo                #=> nil
foo.nil?           #=> true

defined? @bar      #=> nil
instance_variables #=> []
@bar               #=> nil
@bar.nil?          #=> true
# warning: instance variable @bar not initialized

defined? $baz      #=> nil
$baz               #=> nil
# warning: global variable `$baz' not initialized
$baz.nil?          #=> true
# warning: global variable `$baz' not initialized
但是,对于类层次结构变量和常量,情况并非如此:

defined? @@wah     #=> nil
@@wah
# NameError: uninitialized class variable @@wah in Object

defined? QUUX      #=> nil
QUUX
# NameError: uninitialized constant Object::QUUX
这是一条红鲱鱼:

defined? fnord     #=> nil
local_variables    #=> []
fnord
# NameError: undefined local variable or method `fnord' for main:Object
这里出现错误的原因不是单位化局部变量的计算结果不为
nil
,而是
fnord
不明确:它可能是发送给默认接收器的无参数消息(即相当于
self.fnord()
),也可能是对局部变量
fnord
的访问

为了消除歧义,您需要添加一个接收者或参数列表(即使是空的)来告诉Ruby这是一个消息发送:

self.fnord
# NoMethodError: undefined method `fnord' for main:Object
fnord()
# NoMethodError: undefined method `fnord' for main:Object
或者确保解析器(而不是计算器)在使用前解析(而不是执行)赋值,以告诉Ruby它是一个局部变量:

if false
  fnord = 42
end
fnord              #=> nil

当然,
nil
是一个对象(它是类
NilClass
的唯一实例),因此有一个
object\u id
方法。

但是它如何进入
If
块,而入口点被
false
锁定。谁打破了这个锁?对于总是
local
变量的情况并非如此。这是错误的。局部变量只有在定义之后才存在。您可能正在考虑JavaScript。请参阅演示。我想到的是Ruby,而不是Javascript,Ruby确实有一种变量提升形式。但是,我发现您是正确的,在方法中定义变量的时间比第一个变量赋值发生的时间晚。然而,变量仍然被挂起,因为即使没有执行赋值,它也是被定义的。为了澄清上面Jörg的评论——“after”并不意味着执行明智,而是在从左到右、从上到下阅读时出现在源代码中。您的提示很好!所以
+1
来自我。:)嗯?<代码>如果为假;戈谢尔;结束导致静音#⇒ 无。对
TotalCrapGoesher
没有得到计算,表达式返回了
nil
@Entrops抱歉,我不小心把“parsed”读成了“尝试计算”而不是“parsed for syntax.”我的错。当我做下面的
>局部变量时,=>[:name,:\u]
。什么是
?这是另一个局部变量。我不能告诉你它从哪里来,你必须展示你的全部代码。但是,如果您在IRb中尝试了这一点,那么答案是显而易见的:IRb定义的局部变量始终保存最后一个计算表达式的值。是的。我在
IRB
中输入了它。下面是代码
>>局部变量
好的,所以我现在尝试了-
局部变量
如果false>>name=“joy”>>结束>局部变量[/code>,如果false name=“joy”end=>nil局部变量p:::#=>:但在
:(变量名为
是表示变量名的符号文字。
if false
  fnord = 42
end
fnord              #=> nil