0

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 密钥会自动冻结。

4

2 回答 2

2
  • 关于你的第一个问题:

    因为解释器无法预见该字符串实例以后是否会被任何破坏性方法修改。

  • 关于您的第二个问题(在“或”之后):

    通过对 的任何破坏性方法String,例如reverse!prependconcat等。

于 2013-09-27T17:36:33.930 回答
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 语法,但后来又恢复了。

于 2013-12-25T16:55:38.113 回答