2012-04-28 6 views

答えて

5

はい、これはバグですが、少なくとも私はバグと呼んでいます。いくつかの人はこれを "誤って外部に漏れる実装の詳細"と呼んでいますが、それはのバグのための都市の少年の話です。あなたが設定し、それについて知らなくてもセットの要素を変形している

  1. 問題は、主に2つの原因があります。

  2. 標準のRuby Setは、ハッシュとして実装されています。

結果は、あなたがそれについて知ってハッシュせずに内部ハッシュのキーを変更していることであり、それは実際にそれはもう持っている何のキーを知らずに貧しいハッシュを混乱させる。ハッシュクラスはrehash methodがあります

焼き直し→HSH

は、各キーの現在のハッシュ値に基づいてハッシュを再構築します。キーオブジェクトの値が挿入されてから変更された場合、このメソッドはhshを再インデックスします。

a = [ "a", "b" ] 
c = [ "c", "d" ] 
h = { a => 100, c => 300 } 
h[a]  #=> 100 
a[0] = "z" 
h[a]  #=> nil 
h.rehash #=> {["z", "b"]=>100, ["c", "d"]=>300} 
h[a]  #=> 100 

お知らせrehash文書に含まれている例で興味深い振る舞い。ハッシュは、kk.hash値を使用して物事を追跡します。配列をキーとして配列を変更する場合は、配列のhashの値も変更できます。その結果、Hashはその配列をキーとして保持していますが、ハッシュはその配列をキーとして見つけることができません。これは、新しいhash値のバケットを探しているためですが、配列はバケットにあります古いhash値です。しかし、あなたがrehashハッシュの場合、それは突然すべての鍵を再度見つけることができ、老衰はなくなります。配列以外のキーでも同様の問題が発生します。hashの値が変更され、そのキーを含むハッシュが混乱して、rehashまで失われてしまいます。

Set classは、内部的にメンバーを格納するためにHashを使用し、メンバーはハッシュのキーとして使用されます。したがって、メンバーを変更するとSetが混乱します。 Setがrehashメソッドを持っていたら、頭の上にセットしてrehashと頭を叩いて、ある意味でそれをノックすることで、問題を回避することができます。ああ、そのようなメソッドはSetにありません。そして、あなたが正常に動作しますが、キーを変更設定し、あなたのdelete(例えばmember?など、様々な他の方法)にrehashを呼び出すことができます

class Set 
    def rehash 
     @hash.rehash 
    end 
end 

:しかし、あなたは猿で独自にパッチを適用することができます。

関連する問題