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字符串,你只需使用符號。 –