Hugh Sasse wrote:
> On Fri, 16 Sep 2005, Robert Klemme wrote:
>
>> Hugh Sasse wrote:
>
>>> Hmm, that's interesting, but I don't get:
>>>
>>> code << "def hash() " << fields.map {|f| "self.#{f}.hash" }.join(" ^
>>> ") << " end\n"
>>>
>>> Shouldn't hash return a Fixnum?
>>
>> Definitely!
>>
>          [...]
>>> The function above appears to return a string with numbers separated
>>> by " ^ ".
>>
>> Nope.  The join appears during code generation and not during
>> evaluation of the method.  You can easily verify this by printing
>> code after it's completed. :-)
>
> Oh, then it's exclusive or.  I'm clearly being as sharp as a sponge
> today.

I'll have to remember that phrase - I could use it myself from time to
time. :-)

> While my brain is behaving like cottage cheese, it's probably not
> the time to ask how one might guarantee that you don't stomp on the
> hashes of other ojects in the system.  If you have an even number of
> elements, all the same Fixnum, like [1,1,1,1] then they would hash
> to 0, as would [2,2], I "think".
> irb(main):004:0> [1,1].inject(0) { |a,b| a ^= b.hash}
> => 0
> irb(main):005:0> [2,1,1,2].inject(0) { |a,b| a ^= b.hash}
> => 0

Btw, the assignment is superfluous.  The result of a^b.hash is the next
iteration's a.

> irb(main):006:0>

Yes.  The algorithm can certainly be improved on.  Typically you rather do
something similar to

(a.hash ^ (b.hash << 3) ^ (c.hash << 7)) & MAX_HASH

09:53:59 [~]: irbs
>> [2,1,1,2].inject(0) { |a,b| ((a << 3) ^ b.hash) & 0xFFFF_FFFF}
=> 2781
>> [1,2, 1,2].inject(0) { |a,b| ((a << 3) ^ b.hash) & 0xFFFF_FFFF}
=> 1885
>>

i.e. by shifting you make sure that order matters etc.

Kind regards

    robert