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

我尝试浏览RubySpec源代码frozen,但我根本没有看到任何关于 Fixnums 的信息。

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

4

2 回答 2

0

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

可能更令人惊讶的是,冻结1也会冻结n。根据Fixnum 的文档

对于任何给定的整数值,实际上只有一个 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 中尝试了这段代码,得到了相同的结果。

于 2013-05-18T18:02:02.397 回答
0

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

从技术上讲,不是所有的 Fixnums 都“冻结”了(因为你不能修改状态)?

matz回答:

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

因此,理论上,存在冻结固定数字的空间。我不认为这是值得的成本。

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

于 2013-05-18T08:32:47.543 回答