2006/1/24, James Edward Gray II <james / grayproductions.net>:
> On Jan 24, 2006, at 1:06 PM, Robert Klemme wrote:
>
> >> I can't use this code as is.  I assume you didn't set up delegation
> >> quite right:
> >
> > What problem exactly do you have with it?
>
> When I placed the code you posted in a file and tried to create
> WeahHash, the program crashed.  (Wrong number of arguments to
> initialize().)  I assume it would have worked if I passed the Hash
> manually though.

Yep.

> >> class WeakHash < DelegateClass(Hash)
> >>    def initialize
> >>      super(Hash.new)
> >>    end
> >>
> >>    # ...
> >> end
> >
> > No need to inherit to fix this. You can simply do
> >
> > require 'delegate'
> > Wh=DelegateClass(Hash)
> > class Wh
> >   def initialize(h={})
> >     __setobj__ h
> >   end
> > end
>
> Here's another question for you:  What are we gaining by delegating
> to an object here, as opposed to subclassing?

Note, the difference between yours and mine was that you first
delegated and then subclassed the delegating class. I'd say do either
of both in this case but not both.  Generally I'd prefer delegation in
this use case because we really have a case of wrapping and unwrapping
during insertion and retrieval ops. IMHO inheritance is often used in
many cases where it's not appropriate (although in this case you could
argue that a WeakHash is really a Hash - but then again, it doesn't
share some of Hash's basic properties, namely that the contents do not
change suddenly). There's no hard written rule to be found here.

> >> Some questions the above raises for me:
> >>
> >> 1.  What will Ruby do if a key is GCed, but not a value?
> >
> > This was just rough outline code. For a production version I'd
> > probably change it to consider a pair as gone if either of them is
> > GC'ed.
> >
> >> 2.  How does this code deal with a value being GCed when the key
> >> remains?
> >
> > It will yield nil - but see 1.
> >
> >> 3.  Don't we need to shut off GC in places, to keep references from
> >> disappearing before we can use them?
> >
> > No.  Because while the yield takes place instances are hard referenced
> > and cannot be gc'ed.
>
> Good answers all around.  Thanks.

In fact to be really sure, one should probably do something like this:

def each
  __getobj__.each do |wk,wv|
   k,v=wk.__getobj__, wv.__getobj__
  yield unless k.nil? || v.nil?
  end
end

Cheers

robert

--
Have a look: http://www.flickr.com/photos/fussel-foto/