On Mon, Apr 11, 2011 at 5:20 AM, Clifford Heath <no / spam.please.net> wrote:
> On 04/11/11 10:02, Charles Oliver Nutter wrote:
>>
>> The special-cased logic for Fixnums and Symbols in hashes is obviously
>> done for performance purposes. No matter what you do, checking for
>> method redefinitions every single time will have a performance impact.
>
> Yes.
>
>> Even checking an inline cache has an impact.
>
> You are mixing up the situations where there is no sane
> case for allowing modifications, from the many fewer
> ones where there is. No sane person would want to change
> the implementation of 1+1; but someone can and has
> implemented Fixnum+Complex. That works because Fixnum
> will always call coerce where needed, so there's no need
> to guard the optimisations.

I think Charly got it exactly right.

> In the few remaining cases where there is a good case
> for supporting modifications, the minuscule cost of
> a check would be justified. A single variable (saying
> "this class has been modified from its standard form")
> would take up a cache line, but the test would play
> into branch prediction, so the actual effect would be
> tiny.

Frankly, since what you are attempting seems a rather rare case I'd
say it should be the way it is.  After all, you can easily monkeypatch
Hash[] etc. to get the behavior you desire.  That way not 99% of
usages of Hash have to suffer for 1% needing to code less.  I think
that is a fair balance.

I don't understand why you insist on changing a core class for your
rare case of making different classes equivalent and causing potential
harm for many, many users of Ruby instead of just going ahead and also
monkey patch Hash since you did already so for Fixnum.  On one hand
you use Ruby's openness to change core classes to achieve what you
want but on the other you seem to refuse to change another to make
your change complete.  The only reason for this that I can detect is
that you were surprised and your expectations were not met.  But now
since you have learned otherwise what stops you from dealing with the
situation in the pragmatic way that is so typical for Ruby?

> I know you guys have done amazing thing to achieve the
> performance that we now have, but please don't forget
> why people choose Ruby; it's clean and consistent.

... most of the time.  But it also tries to balance reasonable
usability with above than awful performance.

> Another thing that could be done to assist; make sure
> that a Hash only ever calls eql? on objects in the hash,
> not on lookup keys. At least that way, if a non-standard
> object is in the hash, it can still be found using values
> that *it* considers equivalent. This change would cost
> *nothing*, it would just make Ruby more consistent.

But it also would not have any positive impact for all others plus
that a change always brings a certain amount of risk of introducing
errors.  Note though, that there might be situations where you want
the exact opposite: you have a Fixnum key and pass a
SomethingFixnumLinke lookup key and want the match to succeed.  You
can only have it one way.  You happen to need the way that is not
possible right now.

Apart from that it feels more natural to me to let the key passed in
compare internal key for equivalence because this key is what should
determine whether I have a match or not.

>> In this case I think there's a fine line between consistency and
>> zealotry. The *vast* majority of Ruby users will never reopen and
>> modify Fixnum or Symbol,
>
> People don't do it because it doesn't work, not because
> it wouldn't be useful.

How do you know?

> Inability to make classes that act
> like numbers is perhaps the biggest wart on an otherwise
> clean language, on a par with Javascript using float for
> all numbers.

We *can* make classes that act like numbers (as has been demonstrated
often enough).  And this works remarkably well.

>> We've been more conservative than other impls, even.
>
> and yet JRuby's Hash optimises both eql? and hash for Fixnums,
> where MRI only optimises hash.

It is in the nature of optimizations that they are done differently on
different platforms.  Actually they have to because characteristics of
all platforms are different.

Cheers

robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/