Rein Henrichs:
#hash makes sense for Hash# and etc. #eql? makes more
sense for Array#&. I too find it odd that both are necessary.
Both are necessary because #eql? says whether two objects are surely
the same, while #hash says whether they’re surely different – which,
perhaps counterintuitively, is not the same problem.
The difference is that in many, many cases it’s much faster to check
whether two objects are surely different (via a fast #hash function)
than whether they’re surely the same (#eql? can be quite slow).
The main difference betwen #eql? and #hash is that #hash can return the
same value for objects that are not #eql? (but if two objects are #eql?
then #hash must return the same value).
An untested, and definitely not optimal
(but hopefully simple) example follows. 
Imagine that you want to implement a new immutable string class, one
which caches the string length (for performance reasons). Imagine also
that the vast majority of such strings you use are of different lenghts,
and that you want to use them as Hash keys.
class ImmutableString
def initialize string
@string = string.dup.freeze
@length = string.length
end
end
Given the above assumptions, it might make sense for #hash to
return the @length, while #eql? makes the ‘proper’ comparison:
class ImmutableString
def hash
@length
end
alias eql? ==
end
This way in the vast majority of cases, when your ImmutableStrings will
be considered for Hash keys, the check whether a given key exists will
be very quick; only when two objects #hash to the same value (i.e.,
when they’re not surely different) the #eql? is called to tell whether
they’re surely the same.
— Shot
···
--
60.times{|a|puts((0..240).map{|b|x=y=i=0;until(x*x+y*y>4||i==99);
x,y,i=x*x-y*y+b/120.0-1.5,2*x*y+a/30.0-1,i+1;end;i==99?'#':'.'}*'');}
[David Brady]