2012-04-28 3 views

답변

5

예, 이것은 버그이거나 적어도 버그라고합니다. 어떤 사람들은 이것을 "우연히 외부 세계에 새어 나가는 구현 세부 사항"이라고 부르 겠지만, 그것은 단지 버그에 대한 city-boy 대화의 멋진 바지 일뿐입니다. 당신은 설정 그것에 대해 모른 채 설정의 요소를 수정하고

  1. :

    문제는 두 가지 원인이있다.

  2. 표준 Ruby Set은 해시로 구현됩니다.

결과은 당신이 그것에 대해 아는 해시없이 내부 해시의 키를 수정하고 그 정말 더 이상 무슨 키 모르고로 가난한 해시를 혼동한다는 것이다.

재탕의 →의 HSH

각 키에 대한 현재의 해시 값을 기준으로 해시를 재구성 : 해시 클래스는 rehash method가 있습니다. 키 객체의 값이 삽입 된 후 변경된 경우이 메소드는 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 설명서가 포함되어 있습니다. 해시는 k 키 값으로 k.hash 값을 사용하여 사물을 추적합니다. 배열을 키로 사용하고 배열을 변경하는 경우 배열의 hash 값을 변경할 수 있습니다. 그 결과 해시는 그 배열을 여전히 키로 가지고 있지만 해시는 새로운 hash 값을위한 버킷을 찾고 있기 때문에 해시 배열을 키로 찾을 수 없지만 배열은 버켓에있을 것입니다. 이전 hash 값입니다. 그러나 해시가 rehash 인 경우 갑자기 모든 키를 다시 찾을 수있게되고 노인성이 사라집니다. 배열이 아닌 키에서도 비슷한 문제가 발생합니다 : hash 값이 변경되는 방식으로 키를 변경하면 해당 키가 포함 된 해시가 혼동되어 rehash까지 잃어 버릴 수 있습니다.

Set class은 내부적으로 해시를 사용하여 멤버를 저장하며 멤버는 해시의 키로 사용됩니다. 따라서 멤버를 변경하면 Set이 혼란스러워집니다. 세트가 rehash 방법을 가졌다면, 머리 위로 세트를 두드려서 rehash으로 두드려서 문제를 해결할 수 있습니다. 아아, Set에는 그런 메소드가 없다. 그럼 당신은 제대로 작동합니다, 키를 변경 설정하고 delete (예 : member? 등 다양한 다른 방법)에 rehash를 호출 할 수 있습니다

class Set 
    def rehash 
     @hash.rehash 
    end 
end 

: 그러나, 당신은 원숭이에 자신을 패치 할 수 있습니다.

관련 문제