Ruby的standard uri library有很多用于冻结对象的用法,这些对象要么无法修改,要么修改不会造成伤害:
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除了防止修改其接收者之外还有用处吗?
答案 0 :(得分:7)
这个问题的答案可以在这里找到:http://tmm1.net/ruby21-fstrings/
在Ruby 2.1中,&#34; str&#34; .freeze由编译器优化,以在每次调用时返回单个共享冻结字符串。最初实现了另一种&#34; str&#34; f语法,但后来又恢复了。
虽然此功能的外部范围有限,但在内部广泛用于重复删除VM中的字符串。以前,每个def method_missing(),符号:method_missing和任何文字&#34; method_missing&#34;代码库中的字符串都将创建自己的String对象。使用Ruby 2.1,只创建和共享一个字符串。由于许多字符串通常在任何给定的代码库中重复使用,因此很容易相加。事实上,大型应用程序可以预期2.1中的长寿命字符串减少多达30%。
对于2.2,有计划通过新的String #f公开此功能。还有一个关于魔法不可变的提议:字符串注释使得冻结字符串对于给定文件是默认的。
TL; DR:Ruby解析器使用.freeze
处理字符串文字,而不是使用.freeze
的字符串文字。使用.freeze
的字符串不会在每次使用时重新实例化,而是来自全局冻结的字符串池,如符号。
以下是有关此主题的更深入的文章:http://josephyi.com/freeze/