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
将要改变的唯一方法是通过实际执行代码。
这些例子也应该回答你的问题
How could any code change such a string once the interpreter has started running? If we say that "abcd" needs to be frozen, then there must be some way of changing it.
补充说明的第二部分,我想指出的是,“冻结字符串文字”功能,最近已演变,它现在足够将变量标记为frozen
。
In Ruby 2.1, "str".freeze
is optimized by the compiler to return a single shared frozen strings on every invocation. An alternative "str"f syntax was implemented initially, but later reverted.
考虑'mydef.downcase!',它会修改返回的字符串。现在,如果你想在2.1之前的冻结/ interned字符串,你只需使用符号。 –