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

Ruby Fixnum上的冻结行为是否为指定行为?,ruby,rubyspec,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 我试图浏览冻结的源代码,但我根本没有看到任何关于Fixnums的内容 这种行为是否与非MRI Ruby实现的预期行为相同?如果我运行n=1;1.冻

以下是让我有些吃惊的行为:

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
我试图浏览冻结的源代码,但我根本没有看到任何关于Fixnums的内容


这种行为是否与非MRI Ruby实现的预期行为相同?如果我运行n=1;1.冻结;n、 冻结?,在任何Ruby实现上最终的结果都是真的吗?为什么?为什么不?

看起来这是一个预期功能。在本报告中,提出了一个问题:

从技术上讲,不是因为无法修改状态而冻结了所有FixNum吗

matz对此的回答是:

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

因此,从理论上讲,有冷冻的空间。不过我认为这不值得花这么多钱


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

因为Ruby中的所有东西都是对象,所以您可以冻结1可能并不奇怪。符号具有相同的行为。如评论中所述,此行为已从1.8.7冻结不起任何作用更改为1.9+冻结工作

更令人惊讶的是,冻结1也会冻结n。据报道,

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

这意味着n和1是对同一对象的引用,修改其中一个对象将修改另一个对象

您可以通过查看对象id来检查这一点


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

看到这一点,我确实感到惊讶。绝对是a+1!行为从1.8变为1.9,可能从1.9变为2.0,所以你真的在问一个Fixnum的唯一性,即只有一个1,就像只有一个:s是特定于MRI实现的,还是它是一种语言功能?@muistooshort:我的问题是什么。僵硬只是你所描述问题的一个具体例子?我不完全确定。但我也想听听你对这个问题的回答,因为它的独特性,它是一个不可分配的对象,让我惊讶的是它可以被冻结。甚至不能将单例方法添加到Fixnum。我肯定你没有问我,但这就是我感到惊讶的原因。仅供参考,在ruby 2中,所有的固件都是冻结的。
1.object_id
 => 3

n=1
n.object_id
 => 3

n.equal? 1
 => true