On Mon, Mar 20, 2006 at 05:41:56PM +0900, Ross Bamford wrote: > # This WeakHash implementation is by Mauricio Fernandez. I > # just added support for a default, and full key reclaimation > # to suit our need to have the default block run as and when > # (but only when) necessary. > # > # See: http://eigenclass.org/hiki.rb?weakhash+and+weakref I found your message indirectly via my httpd logs :) > class WeakHash #:nodoc: all [...] > def []( key ) > value_id = @cache[key.hash] ======== This will fail when you have hash collisions; I think it should be 'key' as in the original code (same goes for []=). Forcing collisions is not as difficult as one could believe: ##### class WeakHash #:nodoc: all attr_reader :cache def initialize( cache = Hash.new, &initializer ) @cache = cache @initializer = initializer @key_map = {} @rev_cache = Hash.new{|h,k| h[k] = {}} @reclaim_value = lambda do |value_id| if @rev_cache.has_key? value_id @rev_cache[value_id].each_key{|key| @cache.delete key} @rev_cache.delete value_id end end @reclaim_key = lambda do |key_id| if @key_map.has_key? key_id @cache.delete @key_map[key_id] @key_map.delete key_id end end end def []( key ) value_id = @cache[key.hash] if value_id.nil? && @initializer self[key] = @initializer.call(self, key) value_id = @cache[key.hash] end return ObjectSpace._id2ref(value_id) unless value_id.nil? nil end def []=( key, value ) case key when Fixnum, Symbol, true, false key2 = key else key2 = key.hash end @rev_cache[value.object_id][key2] = true @cache[key2] = value.object_id @key_map[key.object_id] = key2 ObjectSpace.define_finalizer(value, @reclaim_value) ObjectSpace.define_finalizer(key, @reclaim_key) end end RUBY_VERSION # => "1.8.4" hash = WeakHash.new hash[["a"]] = "some value" hash[["a"]] # => "some value" hash["c"] # => "some value" -- Mauricio Fernandez - http://eigenclass.org - singular Ruby