我一直在努力更好地理解Ruby,而这里遇到了一些麻烦:
$SAFE = 1
puts $SAFE # 1
proc {
$SAFE = 2
puts $SAFE # 2
}.call
puts $SAFE # 1
以上代码部分取自eRB的源代码重写,以更好地突出显示示例。基本上在proc中,可以将$SAFE
的值设置为任何想要的值,并且在proc之后,SAFE
的值将返回到proc之前的值。
如果不是使用单词$SAFE
而是将其更改为其他单词,例如$DOOR
:
$DOOR = 1
puts $DOOR
proc {
$DOOR = 2
puts $DOOR
}.call
puts $DOOR
那么proc之后$DOOR
的值是2而不是1.为什么两个例子之间存在差异?
答案 0 :(得分:11)
它非常简单,实际上:$SAFE
的行为与您对全局变量的预期不同是因为它不是全局变量。这是一个神奇的独角兽thingamajiggy。
在Ruby中有很多神奇的独角兽故事,遗憾的是它们没有很好的文档记录(事实上并没有完全记录),因为替代Ruby实现的开发人员发现了困难的方法。这些东西都表现得不同,而且(看似)不一致,而且它们共同的唯一两件事就是它们看起来像全局变量,但不像它们那样。
有些人有本地范围。有些具有线程局部范围。有些神奇地改变,没有人分配给他们。有些人对翻译有神奇的意义,并改变了语言的行为方式。有些人还附加了其他奇怪的语义。
$SAFE
几乎具有上述所有内容:它是线程本地的,这意味着如果在一个线程中更改它,它不会影响其他线程。它是本地的,这意味着如果您在本地范围(如类,模块,方法或块)中更改它,它不会影响外部范围(如您所发现的)。它对于解释器具有神奇的意义,因为将其设置为不同于0
的值会使某些事情无效。它还有其他奇怪的语义,你只能增加它的值,而不是减少它。
答案 1 :(得分:3)
我不知道为什么$ SAFE正在以这种方式工作,但我知道它是一个预定义的全局变量,具有与受污染的外部数据和线程相关的神奇含义。
所以不要将它用作程序对象。
请参阅http://ruby-doc.org/docs/ProgrammingRuby/html/taint.html
原则上不应该使用赋值降低$ SAFE的值,但是它附加到执行上下文,例如,多线程程序可以在不同的线程中有多个$ SAFE值。 ..
答案 2 :(得分:1)
$DOOR
的值必须为2。因为$DOOR
全局变量已重新初始化为1到2。关于Global Variables的更多细节。
$SAFE
变量, $SAFE
安全级别。默认情况下是
设为零。
和$SAFE
将在内存中存在,直到范围结束。然后它显示先前设置的值,即1.检查此here以及{{3}的更多内容}