
The Left Hand of Equals - Ice_cream_suit
http://lambda-the-ultimate.org/node/5509
======
nickbauman
I've found that the concept of identity and its relationship to equals in OO
is a _confusion._ And by confusion, I mean an accidental combination that
creates _accidental_ complexity. Because in the OO I've seen, you have a
permanent fusion of of state and identity. Which is to say what happens to the
object is the same thing as the object. Which is not true about things in the
real world at all. Does this paper address this problem?

~~~
dnomad
The real problem is that equality is an __operator __that creates a relation
between two objects. Equality is not and should never be decided by one object
-- both objects must "agree". An object A _in itself_ cannot say for sure that
another object B is equal unless A asks B (and then B asks A leading to
infinite recursion). The classic case of this, as pointed out in the paper, is
inheritance which is the prime culprit for broken symmetry eg:

Point a = ...;

ColoredPoint b = ...;

a.equals(b) // false, a says b is not a 'Point'

b.equals(a) // true, b says my 'color-ness' is irrelevant, I'm a Point --
represent!

The only way to ensure that a. equals(b) and b.equals(a) is always true is to
reify the equality relation into its own first-class type or method.

class Point { public static boolean operator_equals(Point a, Point b); }

It's too bad that Java and other languages do not offer first class support
for operators. a == b can be shorthand for Point.operator_equals(a, b). If
there is any ambiguity at all (because b is a subclass and there exists a
method ColoredPoint.operator_equals()) then raise an error and force the
developer to be explicit about exactly which equality operator is intended. If
such a method doesn't exist then _raise an error_ and force the developer to
say exactly what is intended by equality. (Don't fall back to reference
equality!).

This would eliminate a whole lot of bugs and all the confusion around
equality.

~~~
dfee
I re-read your comment a couple times, and understood your main point to
succinctly be this:

If `Point` is a subclass of `ColoredPoint`, and `p` and `cp` exist as
instances respectively, there is ambiguity between `p == cp` and `cp == p`.

In Python there is first class support for operators: the `eq` dunder method:

    
    
        def __eq__(self, other):
            if not isinstance(other, type(self)):
                return False
            return self.point == other.point
    

This ambiguity is hard to solve around.

~~~
repsilat
A solution was suggested by the grandparent: make `a==b` call _both_ equality
methods.

Dunno if you raise or just return false if they disagree.

~~~
munificent
I was working on a hobby language a few years ago and trying to figure out a
way to handle equality to avoid these problems. One solution I considered was:

1\. Ask the LHS for its equality function.

2\. Ask the RHS for its equality function.

3\. If the two return different functions (non-identical), the objects are not
equal.

4\. Otherwise, return the result of invoking the function.

The first two steps are polymorphic, so objects can define interesting
equality semantics with whatever policy makes sense for them. But step 3
ensures that the two objects must _agree_ on that policy before you can
compare them.

~~~
repsilat
> One solution I considered

It sounds pretty reasonable, but I have no idea how "sounds reasonable"
correlates with "is helpful in practice". (I think one of the commenters in
the linked page might have raised that point too.)

Fulfilling axioms of equality definitely _does_ sound useful for being able to
write code, though -- having symmetry, not having to think about whether you
need to write `a==b` or `b==a`, seems like it'd lighten the cognitive load.

I suppose also when the objects disagree about equality you also have some
license to say "this may not do quite what you expect" and do your best to
make the most of it.

> I was working on a hobby language a few years ago

Hah, you're famous enough that we've all probably heard of the language if it
has seen the light of day ;-).

My own hobby language has no methods or dynamic dispatch of any kind, haha.
It's a little stressful to have to come up with some equality rule that works
for essentially every use-case, though -- I don't think it's sufficient to
enumerate the data types in the language, I really have to go over all the
ways I think they could be used :-/.

Oh well, it's fun at least.

------
mtreis86
Direct link
[http://web.cecs.pdx.edu/~black/publications/egal.pdf](http://web.cecs.pdx.edu/~black/publications/egal.pdf)

------
skybrian
A lot of the complexity comes from having a top-level type (Object) and
inheritance. Functional languages often don't have this, so comparing two
objects of different types doesn't come up. (Collections don't contain objects
of different types either.)

~~~
myWindoonn
Sure, but most functional languages don't permit useful comparisons between
functions of same type either, so while the complexity is limited, the power
is limited as well.

~~~
skybrian
Well, an equality function could be defined that compares closure values and
instructions, as mentioned in the article.

As I understand it, the reason it isn't typically done is conceptual: two
functions are mathematically equal if the same inputs produce the same
outputs. (The same way you'd define equality for a hashmap by comparing keys
and values.) But this is impossible to calculate for arbitrary functions.

------
Terr_
I'm assuming the title supposed to be a reference to The Left Hand of Darkness
[0], a book that also deals with equality and comparisons.

[0]
[https://en.wikipedia.org/wiki/The_Left_Hand_of_Darkness](https://en.wikipedia.org/wiki/The_Left_Hand_of_Darkness)

Edit: Ah, the reference is explicit inside the linked PDF, but I'll leave this
up for anybody else is ctrl-f-ing to satisfy the same curiosity.

------
mcnamaratw
The identity stuff is fine.

But the talk about OO philosophy is the same old fool's gold. OO is a very
useful filing system for organizing large amounts of code. Sure, code
organization can tend to mirror code function, and even sometimes in some ways
mirror parts of the application space. Philosophers could talk about that, but
it's philosophy not coding.

The philosophy is a distraction, especially for new people learning OO.

So OO as a 'model of reality'? OO is a model of reality to about the same
extent that the Dewey Decimal System is a model of reality. Every branch of
"OO philosophy" that doesn't make this simple point clear is a barrier to
entry.

