【发布时间】:2019-09-18 08:19:31
【问题描述】:
这个问题特别适用于 Ruby 1.9 和 2.1,其中字符串文字不能自动冻结。特别是我指的是this article,它建议冻结字符串,以便重复评估代码不会每次都创建一个新的字符串对象,据说还有其他优点可以使程序性能更好。作为一个具体的例子,本文提出了表达方式
("%09d".freeze % id).scan(/\d{3}/).join("/".freeze)
我想在我们的项目中使用这个概念,出于测试目的,我尝试了以下代码:
3.times { x="abc".freeze; puts x.object_id }
在 Ruby 2.3 中,这每次都打印相同的对象 ID。在语言级别与 Ruby 1.9 对应的 JRuby 1.7 中,它会打印三个不同的对象 ID,尽管我已经明确地冻结了字符串。
有人能解释一下原因吗,在这种情况下如何正确使用freeze?
【问题讨论】:
-
字符串实习使字符串不可变,但使字符串不可变并不能保证字符串实习。
freeze合约仅指定它将使字符串不可变,不多也不少。字符串是否被interned没有定义,每个实现都可以自己选择行为。 -
@JörgWMittag:怎么会这样?在
unfreeze,您只需将其复制到其他地方(这样对“规范”冰柱的任何引用都将保持有效)。这显然改变了object_id,但是......我认为Hash已经做了类似的事情......a = "foo"; b = { a => 1 }; a.object_id == b.keys.first.object_id是错误的 -
大声笑,你是对的(除了shenanigans)。