gpt4 book ai didi

ruby - 当文件被 Ruby 解析时,为什么常量不像局部变量那样初始化?

转载 作者:行者123 更新时间:2023-12-03 23:46:40 24 4
gpt4 key购买 nike

在 Ruby 中,我知道我可以做这样的事情:

if false
var = "Hello"
end

puts var

应用程序不会崩溃,并且 var简单地设置为 nil .我读到这是由于 Ruby 解析器的工作方式造成的。

为什么同样不适用于常量?
if false
MY_CONST = "Hello"
end

puts MY_CONST
=> uninitialized constant MY_CONST (NameError)

最佳答案

TL; 博士

局部变量在解析器遇到时被定义,而常量则不是。但是,在解释器评估时必须定义两者以避免 NameError。

分析

局部变量由解析器自动激活

您的原始代码实际上并未为局部变量或常量赋值。在这两种情况下,if false永远不会为真,因此永远不会执行赋值语句。但是,解析器对 undefined variable 和常量的处理方式不同。

撇开范围问题不谈,local variables在解析器遇到赋值时创建,而不仅仅是在赋值发生时创建。所以,即使:

if false
var = "Hello"
end

从不执行赋值,它仍然将局部变量初始化为 nil .

另一方面,常量的处理方式不同。在当前命名空间中不可用的未知常量(实际上,任何以大写字母开头的内容)将引发 NameError。

在新的 irb session 中,这两个都会引发 NameError,但异常消息略有不同:

puts var
#=> NameError (undefined local variable or method `var' for main:Object)

puts MY_CONST
#=> NameError (uninitialized constant MY_CONST)

但是,如果您更改分支逻辑以便解释器评估具有 undefined variable 的表达式,您也会得到 NameError:

if baz
puts true
end

#=> NameError (undefined local variable or method `baz' for main:Object)

检查行为的另一种方法

启动新的 irb session 。然后:

irb(main):001:0> defined? var
#=> nil
irb(main):002:0> if false then var = 1 end
#=> nil
irb(main):003:0> defined? var
#=> "local-variable"

您可以看到 var 已定义并设置为 nil当解析器遇到时,即使从未计算赋值表达式。但是,常量不会自动激活:

irb(main):004:0> defined? MY_CONST
#=> nil
irb(main):005:0> if false then MY_CONST = 1 end
#=> nil
irb(main):006:0> defined? MY_CONST
#=> nil
irb(main):007:0> MY_CONST
#=> NameError (uninitialized constant MY_CONST)

结论

虽然我猜这种行为与解析器和解释器之间的差异有关,也可能与用于变量/方法查找与常量查找的命名空间之间的差异有关,但我无法真正告诉您为什么需要差异(如果真的是),或者即使它在所有 Ruby 实现中都相同。这是各种 Ruby 引擎开发人员的问题,包括 Ruby 核心团队。

但是,实际上,当您尝试使用 undefined variable 或常量时,您总是会遇到 NameError 异常。因此,这种差异对现实世界的影响(如果有的话)很小。所有语言都有怪癖;这可能是其中之一,但除了人为的例子之外,很难看出这将如何导致实际问题。您的里程肯定会有所不同。

关于ruby - 当文件被 Ruby 解析时,为什么常量不像局部变量那样初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62302469/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com