Fixnum上的冻结行为是否为指定行为?

时间:2013-05-18 06:49:41

标签: ruby rubyspec

这种行为让我感到有些惊讶:

1.9.3-p392 :001 > n = 1
 => 1
1.9.3-p392 :002 > n.frozen?
 => false
1.9.3-p392 :003 > 1.freeze
 => 1
1.9.3-p392 :004 > n.frozen?
 => true

我尝试了frozen的{​​{1}}源代码,我根本没有看到任何关于Fixnums的内容。

这种行为与非MRI Ruby实现的预期相同吗?如果我运行n = 1; 1.freeze; n.frozen?,那么任何Ruby实现的最终结果总是true吗?为什么或为什么不呢?

2 个答案:

答案 0 :(得分:0)

看起来它是一个预期的功能。在Ruby Forum中,提出了一个问题:

  

从技术上讲,所有Fixnums都没有“冻结”(因为你无法修改状态)?

matz回答:

  

不是,因为fixnums可能有实例变量。

     

因此,从理论上讲,存在冻结固定物的空间。我不认为这是值得的。

不同的MRI Ruby版本之间似乎存在意外的不一致,但就MRI而言,它们看起来像是被识别为错误,并且已被修复。您观察到的规范似乎是预期的规范。

答案 1 :(得分:0)

由于Ruby中的所有内容都是一个对象,因此您可以冻结1也就不足为奇了。 Symbol具有相同的行为。正如评论中所提到的,这种行为从1.8.7(冻结没有做任何事情)变为1.9+(冻结作品)。

更令人惊讶的是冻结1也会冻结n。根据{{​​3}},

  

对于任何给定的实际上只有一个Fixnum对象实例   整数值

这意味着n1是对同一对象的引用,修改一个将修改另一个。

您可以通过查看object_id

自行查看
1.object_id
 => 3

n=1
n.object_id
 => 3

n.equal? 1
 => true

我在MRI 1.8.7,MRI 2.0.0,JRuby和Rubinius中尝试了这个代码并得到了相同的结果。