Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: martin odersky <martin.odersky-p8DiymsW2f8 <at> public.gmane.org>
Subject: Rethinking equality
Newsgroups: gmane.comp.lang.scala.internals
Date: Saturday 7th May 2011 09:56:52 UTC (over 5 years ago)
Now that 2.9 is almost out the door, we have the luxury to think of what
could come next. One thing I would like to address is equality. The current
version did not age well; the longer one looks at it, the uglier it gets.
In
particular it is a great impediment for DSL design. Witness the recent
popularity of === as an alternative equality operator. I previously thought
we were stuck with Java-like universal equality for backwards compatibility
reasons. But there might be a workable way out of that morass. It works in
three steps, which would coincide with the next three major revisions of
Scala (yes, sometimes progress has to be slow!)

Step 1:
=====

Introduce the standard Equals type class:

class Equals[T] {
  def eql(x: T, y: T)
}

And put the following method in Predef:

  @inline def areEqual[T](x: T, y: T)(implicit eq: Equals[T]) = eq.eql(x,
y)

Define equality as follows:

  X == Y  is equivalent to areEqual(X, Y), if that typechecks, and
otherwise
equivalent to what it was until now (i.e. universal equality)

[Aside: I note that the spec still defines Any.== to be

   if (null eq this) null eq that else this equals that

We should update that to reflect the realities wrt boxed numbers (on the
other hand, if we continue down the path I outline, those realities will
also change, see below).]

Furthermore, issue a warning if there is an Equals[T] class for one of the
types of X and Y, but not the other (in that case we fall back to the
default behavior).

The effect of step 1 is just that any implicit Equals definitions override
default behavior, so we are backwards compatible.

Step 2:
======

Define equality as follows:

  X == Y  is equivalent to areEqual(X, Y), if there is an implicit
Equals[T]
value for at least one of the types T of X or Y.

Otherwise it is equivalent to universal equality, but in that case a
warning
is issued.


Step 3:
======

Define equality as follows:

  X == Y  is equivalent to areEqual(X, Y).

Here's an example: Let's say we have a class Person with an implicit
Equals[Person].
Let's assume:

  p, q: Person
  a, b: Any

Then we have

           Step1           Step2              Step3
  p == q   implicit        implicit           implicit

  p == a      universal       error              error
  a == p   + warning

  a == b   universal       universal          error
                           + warning

Notes:

1. Of course I assume everywhere that X != Y is !(X == Y).
2. Once we have arrived at step 3, the universal equality logic for boxed
numbers would go into
the implicit equalities for these numbers.
3. All logic we have now in the compiler that warns of equalities that are
always true or false is no longer needed.
 
CD: 3ms