From: ES Date: 2005-03-14T06:08:35+09:00 Subject: Re: how do I convince Hash that two keys are the same? In data 3/13/2005, "Sam Roberts" ha scritto: >(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. When you derive, you establish an is_a relationship. Str is_a String. All methods are also derived so you're actually calling Str#downcase, although the code being executed was defined in String. You'd possibly want to alias hash to old_hash and then call self.downcase.old_hash, which seems to be what you're trying to do. >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. E