From: Sam Roberts Date: 2005-03-14T05:46:42+09:00 Subject: Re: how do I convince Hash that two keys are the same? (I sent this to ruby-doc by accident, and got a response, but I am reposting to ruby-talk, sorry for the cross-post.) Thanks, thats very informative, and I would not have guessed. I tried a different approach, I derived from String. This has the very odd behaviour of blowing the Stack! class Str < String def hash; self.downcase.hash; end # <- this doesn't look recursive # to me, but it blows the stack end h = { } k = Str.new('a') k == 'A' 'A' == k h[k] = 'lower' k = Str.new('A') p k.downcase # Should return an instance of String, right? p k.downcase.hash # <--- this line cause stack overflow k.hash == 'a'.hash h.has_key? k I think Str#downcase should return the same thing as String#downcase => a String, and not a Str, so I don't see why there is a recursive call, here. What am I missing? Thanks, Sam Quoting g_ogata@optushome.com.au, on Mon, Mar 14, 2005 at 05:41:40AM +1100: > Sam Roberts writes: > > > I've tried: > > > > > > h = { } > > > > k = 'a' > > > > class << k > > def hash; self.downcase.hash; end > > def ==(s); self.downcase == s.downcase; end > > def eql?(s); self == s; end > > def ===(s); self == s; end > > end > > > > k = 'A' > > > > class << k > > def hash; self.downcase.hash; end > > def ==(s); self.downcase == s.downcase; end > > def eql?(s); self == s; end > > def ===(s); self == s; end > > end > > > > k == 'a' > > k.hash == 'a'.hash > > > > # I want this to be true! > > h.has_key? k > > > > But it doesn't work. I'm particularly confused because if I write a > > class Str that wraps String and defines those methods things do work > > out... > > > > Any pointers? > > This looks like a consequence of the fact that when ruby takes the > hash of a key, if the key is a String, it uses the default > implementation of String#hash directly, even if String#hash has been > redefined, or the object has a singleton class. (The same thing is > true with Fixnums and Symbols.) > > Try: > > class String > def hash > puts '!' > super > end > end > > {}['a'] = 1 > > Then change the String to an Object. > > HTH. > >