#freeze除防止修改外还有其他用途吗?

Ruby的标准uri库有很多用于冻结对象的用法,这些对象要么无法修改,要么修改不会造成伤害:

user, password = ui.split(':'.freeze, 2) # from generic.rb 

String#split不会修改它的参数,即使它确实如此,代码也能正常工作(Ruby将在下次调用时使用’:’的新实例)。

以下是对无法更改的对象进行冻结的更多用法(这些都来自generic.rb )

  if @scheme && @scheme != "ftp".freeze v.delete!("\t\r\n".freeze) str << ':'.freeze 

为什么有这么多看似不必要的#freeze调用? #freeze除了防止修改其接收器之外还有其他用途吗?

这个问题的答案可以在这里找到: http : //tmm1.net/ruby21-fstrings/

在Ruby 2.1中,编译器优化“str”.freeze,以便在每次调用时返回单个共享冻结字符串。 最初实现了另一种“str”f语法,但后来又恢复了。

虽然此function的外部范围有限,但在内部广泛用于在VM中删除字符串。 以前,每个def method_missing(),符号:method_missing和代码库中的任何文字“method_missing”字符串都将创建自己的String对象。 使用Ruby 2.1,只创建和共享一个字符串。 由于许多字符串通常在任何给定的代码库中重复使用,因此很容易加起来。 实际上,大型应用程序可以预期2.1中的长寿命字符串减少多达30%。

对于2.2,有计划通过新的String #f公开此function。 还有一个魔术不可变的提议:字符串注释,使冻结字符串默认为给定文件。

TL; DR:Ruby解析器使用.freeze处理字符串文字, .freeze不是没有.freeze的字符串文字。 带有.freeze字符串不会在每次使用时重新实例化,而是来自像符号这样的全局冻结字符串池。

这是一篇关于这个主题的更深入的文章: http : //josephyi.com/freeze/