0

Ruby 2.1 は凍結された文字列を持つため、インタープリターが実行されるたびにオブジェクトが再作成されることはありません。つまり、

my_hash["abcd"f] = 123

この文字列が変更されないことをインタープリターが自動的に検出できず、自動的にフリーズできないのはなぜですか?

または、Ruby 2.1 より前の場合、インタープリターが実行を開始すると、どのようなコードでそのような文字列を変更できますか? 「abcd」を凍結する必要があると言うなら、それを変更する何らかの方法があるに違いありません。

-- 更新: 上記の質問が更新されたため、以下のコメントは少し厄介ですが、以前のコード例はあまり良くありませんでした。

-- 更新: http://globaldev.co.uk/2014/05/ruby-2-1-in-detail/ Ruby キーは自動的に凍結されます。

4

2 に答える 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は、実際にコードを実行することです。

これらの例は、質問の2番目の部分にも答える必要があります

インタープリターが実行を開始すると、コードはどのようにそのような文字列を変更できますか? 「abcd」を凍結する必要があると言うなら、それを変更する何らかの方法があるに違いありません。

補足として、「凍結された文字列リテラル」機能が最近進化し、変数に としてフラグを立てるだけで十分であることを指摘しておきますfrozen

Ruby 2.1 では、"str".freezeすべての呼び出しで 1 つの共有凍結文字列を返すようにコンパイラによって最適化されています。代わりの "str"f 構文が最初に実装されましたが、後に元に戻りました。

于 2013-12-25T16:55:38.113 に答える