Ruby 2.1将有一个冻结的字符串,这样每次解释器运行时都不会重新创建对象,即
my_hash["abcd"f] = 123
为什么解释器不能自动检测到这个字符串不会改变而只是自动冻结它?
或者,pre-ruby 2.1一旦解释器开始运行,任何代码如何改变这样的字符串?如果我们说“abcd”需要被冻结,那么必须有一些方法来改变它。
- 更新:上面的问题已经更新,所以下面的评论有点尴尬,但是解决了之前不太好的代码示例。
- 更新:http://globaldev.co.uk/2014/05/ruby-2-1-in-detail/ Ruby密钥会自动冻结。
答案 0 :(得分:2)
关于你的第一个问题:
因为解释器无法预见该字符串实例后来是否会被任何破坏性方法修改。
关于你的第二个问题(在“或”之后):
String
上的任何破坏性方法,例如reverse!
,prepend
,concat
等
答案 1 :(得分:1)
Ruby是一种动态语言。没有静态编译,解释器很难提前知道谁最终会访问和修改变量。
让我们看看下面的例子。你有一个string
str = "foo"
然后在你的代码中有
str.upcase!
# => "FOO"
即使对于一个简单的解析器来理解字符串是变异的,这个例子也是微不足道的。但是,让我们增加一些复杂性
str = "foo"
method = ["up", "case"]
str.send((method << "!").join)
# => "FOO"
这产生与之前完全相同的结果,但该方法在脚本中没有静态编码。相反,它是在运行时对字符串动态执行的计算结果。
但是等等,让它变得更加复杂。
str = "foo"
method = [ARGV.first, "case"]
str.send((method << "!").join) if ARGC.to_i > 0
# => "FOO"
在这种情况下,假设我从命令行传递一个参数,将计算转换方法,然后将其应用于字符串。
你可以猜到,两种情况下知道str
将要改变的唯一方法是实际执行代码。
这些例子也应该回答你问题的第二部分
解释器开始运行后,任何代码如何更改这样的字符串?如果我们说“abcd”需要被冻结,那么必须有一些方法来改变它。
作为旁注,我想指出“冻结字符串文字”功能最近已经发展,现在足以将变量标记为frozen
。
在Ruby 2.1中,编译器优化
"str".freeze
以在每次调用时返回单个共享冻结字符串。最初实现了另一种“str”f语法,但后来又恢复了。