On Sat, Dec 31, 2011 at 13:58, Robert Klemme <shortcutter / googlemail.com> wrote:
> On Fri, Dec 30, 2011 at 3:43 PM, Nikolai Weibull <now / bitwi.se> wrote:

>>> But still, I don't see the need. Note also that a proper Hash key
>>> usually should be immutable because changing them causes all sorts of
>>> trouble if not done carefully.
>>
>> Hence the use of °»value object°… in my question.

> I can't see that "value object" implies "immutable".
>
> http://c2.com/cgi/wiki?ValueObject
> http://en.wikipedia.org/wiki/Value_object

Continue reading:

http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable

>> Second, let me rephrase my
>> question and add some additional context and examples:
>>
>> What algorithm should one employ in the calculation of the hash value
>> of an arbitrary value object?

> There is no single standard (or best) way. The fact that different
> languages (Java, Ruby...) have different means to calculate combined
> hash values which all seem to work pretty well indicates this IMHO.

Really?  Everyone seems to use the XOR method (with good cause).

As I°«ve already pointed out, internally, Ruby does something
completely different.

>> I would claim that the algorithm should take the class of the object
>> into account as well, both for consistency with #== (which should
>> check equality of the classes of the objects being compared) and for
>> added entropy.

> You pay a price for additional calculation though.

Since the fields are immutable, the result of the calculation can be
cached, so that°«s not a valid reason to exclude it.

>> Internally, Ruby (primarily) uses three C functions for the
>> calculation of combined hash values, namely rb_hash_start,
>> rb_hash_uint, and rb_hash_end. As an example, the hash value of a
>> Struct is calculated (in Ruby with these three functions wrapped in an
>> imaginary module C) as
>>
>> class Struct
>> def hash
>>  C.rb_hash_end(reduce(C.rb_hash_start(self.class.hash)){ |h,|
>> C.rb_hash_uint(h, v.hash) })
>> end
>> end
>>
>> Might it be useful to have Ruby expose a way to perform this
>> calculation from the Ruby realm so that other classes may employ this
>> algorithm?

> Not sure whether we would really gain that much. Those calls are
> efficient in C but if you provide that mechanism in Ruby land you will
> have multiple calls, e.g.
>
> def hash
> h = Fixnum::HASH_START
> h = h.combine_hash(@a)
> h = h.combine_hash(@b)
> h = h.combine_hash(@c)
> end

I don°«t understand what you°«re getting at with this example.  It
doesn°«t seem to add anything to the discussion.  My example code,
which shows how Ruby does it internally for Struct, makes multiple
calls.  Since these methods would be simple wrappers of the C
functions, the hash calculation would (almost) be as fast as it would
be for Struct.