(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 <sroberts / uniserve.com> 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.
>
>