加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 与错误的`if`块内的赋值操作混淆

发布时间:2020-12-17 01:47:02 所属栏目:百科 来源:网络整理
导读:参见英文答案 I don’t understand ruby local scope????????????????????????????????????5个 我正在玩if块中的赋值操作,并发现了以下结果,这让我感到惊讶: C:irb --simple-promptif falsex = 10end#= nilp xnilx.object_id#= 4#= nilp yNameError: undef
参见英文答案 > I don’t understand ruby local scope????????????????????????????????????5个
我正在玩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>'

在上面的代码中,您可以看到x局部变量已经创建,即使它仅被分配给falsy if块.我试图用p x来查看x的内容,这迫使我相信分配没有完成,但x变量存在. x.object_id也证明了这种情况.

现在我的问题是如何创建x局部变量,即使if块入口点是故意关闭的?

我期望p x的输出类似于p y的输出.但相反,我从p x得到了一个令人惊讶的答案.

有人可以向我解释这个概念是如何运作的吗?

编辑

不,这是另一个测试.仅局部变量不是这种情况.实例和类变量也是如此.见下文:

class Foo
  def show
    @X = 10 if false
    p @X,"hi",@X.object_id
  end
end
#=> nil
Foo.new.show
nil
"hi"
4
#=> [nil,4]

class Foo
  def self.show
    @@X = 10 if false
    p @@X,@@X.object_id
  end
end
#=> nil
Foo.show
nil
"hi"
4
#=> [nil,4]

成功案例:

class Foo
  def self.show
    @@X = 10 if true
    p @@X,@@X.object_id
  end
end
#=> nil
Foo.show
10
"hi"
4
#=> [10,4]

解决方法

在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_id方法.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读