July 26, 2014
On Saturday, 26 July 2014 at 06:50:11 UTC, Manu via Digitalmars-d wrote:
> It's okay, I hate it too.
> But I equally can't abide == meaning something different than <, <=, etc.
> That's insane.

Yes, it is unsound to use opCmp for types that aren't totally ordered:

http://en.wikipedia.org/wiki/Partially_ordered_set

«In general two elements x and y of a partial order may stand in any of four mutually exclusive relationships to each other: either x < y, or x = y, or x > y, or x and y are incomparable (none of the other three). A totally ordered set is one that rules out this fourth possibility: all pairs of elements are comparable and we then say that trichotomy holds. The natural numbers, the integers, the rationals, and the reals are all totally ordered by their algebraic (signed) magnitude whereas the complex numbers are not.»

> Like I said, I'm just absolutely astonished that people think the situation
> in your OP is okay, especially when the solution is so obvious.

Right, when you only have 3 states, you should require total order.

July 26, 2014
On Saturday, 26 July 2014 at 07:42:05 UTC, Ola Fosheim Grøstad wrote:
> On Saturday, 26 July 2014 at 06:50:11 UTC, Manu via Digitalmars-d wrote:
>> It's okay, I hate it too.
>> But I equally can't abide == meaning something different than <, <=, etc.
>> That's insane.
>
> Yes, it is unsound to use opCmp for types that aren't totally ordered:

Yes, that's why it's possible to provide opEquals in addition to opCmp. But for the vast majority of cases, opEquals _is_ equivalent to opCmp == 0, and element-wise equality is not. Defining opEquals to be the latter by default _even in the presence of opCmp_ is therefore wrong in almost all cases.
July 26, 2014
On 7/26/14, 2:19 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
> On Saturday, 26 July 2014 at 07:42:05 UTC, Ola Fosheim Grøstad wrote:
>> On Saturday, 26 July 2014 at 06:50:11 UTC, Manu via Digitalmars-d wrote:
>>> It's okay, I hate it too.
>>> But I equally can't abide == meaning something different than <, <=,
>>> etc.
>>> That's insane.
>>
>> Yes, it is unsound to use opCmp for types that aren't totally ordered:
>
> Yes, that's why it's possible to provide opEquals in addition to opCmp.
> But for the vast majority of cases, opEquals _is_ equivalent to opCmp ==
> 0, and element-wise equality is not. Defining opEquals to be the latter
> by default _even in the presence of opCmp_ is therefore wrong in almost
> all cases.

Case-insensitive ordering is a simple example. Field for field comparison is the right default whether or not opCmp is defined.

Andrei

July 26, 2014
I agree that the documentation needs improvement.

It needs to be defined what kind of relation opCmp is meant to model.

If it's concept is a partial order, opEquals cannot be inferred.

If it's concept is a strict weak ordering [1, 2], which is required for sorting, opEqual can be inferred.

[1] https://www.sgi.com/tech/stl/StrictWeakOrdering.html
[2] https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings
July 26, 2014
On Saturday, 26 July 2014 at 09:48:55 UTC, Andrei Alexandrescu wrote:
> On 7/26/14, 2:19 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
>> Yes, that's why it's possible to provide opEquals in addition to opCmp.

Not quite, opCmp would then have to throw if opCmp(a,b) is incomparable. Conflating incomparable and equal values as 0 is a bad idea when sorting. That means incomparable values are sprinkled randomly over the sort.

> Case-insensitive ordering is a simple example.

That doesn't sound right. "<=" is defined for all possible pairs. Case insensitive ordering satisfies the totality requirement: (a <= b or b <= a), for all strings a and b?
July 26, 2014
On Saturday, 26 July 2014 at 10:43:08 UTC, Ola Fosheim Grøstad wrote:
> On Saturday, 26 July 2014 at 09:48:55 UTC, Andrei Alexandrescu wrote:
>> On 7/26/14, 2:19 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
>>> Yes, that's why it's possible to provide opEquals in addition to opCmp.
>
> Not quite, opCmp would then have to throw if opCmp(a,b) is incomparable. Conflating incomparable and equal values as 0 is a bad idea when sorting. That means incomparable values are sprinkled randomly over the sort.

Ok, I see what you mean, and I agree. If you can have incomparable elements, you cannot sort reliably.

But you were responding to Manu:

> But I equally can't abide == meaning something different than <, <=, etc.
> That's insane.

I somehow took your response as disagreement with him.
July 26, 2014
On Saturday, 26 July 2014 at 09:48:55 UTC, Andrei Alexandrescu wrote:
> On 7/26/14, 2:19 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
>> On Saturday, 26 July 2014 at 07:42:05 UTC, Ola Fosheim Grøstad wrote:
>>> On Saturday, 26 July 2014 at 06:50:11 UTC, Manu via Digitalmars-d wrote:
>>>> It's okay, I hate it too.
>>>> But I equally can't abide == meaning something different than <, <=,
>>>> etc.
>>>> That's insane.
>>>
>>> Yes, it is unsound to use opCmp for types that aren't totally ordered:
>>
>> Yes, that's why it's possible to provide opEquals in addition to opCmp.
>> But for the vast majority of cases, opEquals _is_ equivalent to opCmp ==
>> 0, and element-wise equality is not. Defining opEquals to be the latter
>> by default _even in the presence of opCmp_ is therefore wrong in almost
>> all cases.
>
> Case-insensitive ordering is a simple example. Field for field comparison is the right default whether or not opCmp is defined.

If you're starting with the premise that the user's intention was to keep the default semantics of opEquals, then yes. I just find this unlikely. To take your example, I for one would fully expect "hello WORLD" and "Hello World" to be considered equal in all circumstances, not just when sorting.

If you want it to be restricted to sorting, it should probably not be a property of the type, but a predicate should be used instead for sorting. If you still want it to be different, just define an opEquals, it's trivial using `tupleof`.

Indeed, both options make assumptions about the user's intentions, but IMO the assumption for opEquals not using opCmp is the more unlikely one. Maybe we can then at least require the user to specify explicitly what she wants, as H.S. Teoh (?) suggested? Maybe for now implement whatever has been the default before to minimize breakage, but deprecate it with an appropriate message, and remove it a few releases down the road?
July 26, 2014
On Saturday, 26 July 2014 at 12:19:41 UTC, Marc Schütz wrote:
> I somehow took your response as disagreement with him.

No, I think it is useful to have a default total sort order for types even if the order isn't natural and might appear arbitrary. It is useful in binary trees etc.

That does not mean that you should also define comparison and equality, just because you have a default total order for sorting.

The constraints put on comparison operators are too restrictive for domain specific types (such as fuzzy numbers, intervals etc)
July 26, 2014
On Saturday, 26 July 2014 at 10:22:54 UTC, Fool wrote:
> I agree that the documentation needs improvement.
>
> It needs to be defined what kind of relation opCmp is meant to model.
>
> If it's concept is a partial order, opEquals cannot be inferred.
>
> If it's concept is a strict weak ordering [1, 2], which is required for sorting, opEqual can be inferred.

I don't think so.

NaN < x is false
NaN > x is false

if you try to derive equality from that you would get:

NaN == x is true

For sorting you are obviously better off defining NaN as in a manner that is consistent with the other values of the type. E.g. preceding all other float values.
July 26, 2014
On Saturday, 26 July 2014 at 13:25:06 UTC, Ola Fosheim Grøstad wrote:
> On Saturday, 26 July 2014 at 10:22:54 UTC, Fool wrote:
>> It needs to be defined what kind of relation opCmp is meant to model.
>>
>> If it's concept is a partial order, opEquals cannot be inferred.
>>
>> If it's concept is a strict weak ordering [1, 2], which is required for sorting, opEqual can be inferred.
>
> I don't think so.
>
> NaN < x is false
> NaN > x is false

...which means that < as it is usually defined on floating point numbers does not define a strict weak ordering.

This suggests that opCmp should not be required to model a (strict) weak ordering. On the other hand this means that sorting is not defined by opCmp.

The last fact is documented at http://dlang.org/phobos/std_algorithm.html#sort


> if you try to derive equality from that you would get:
>
> NaN == x is true

This is not a contradiction to what I wrote.


> For sorting you are obviously better off defining NaN as in a manner that is consistent with the other values of the type. E.g. preceding all other float values.

...which means that you are extending the partial order to a particular total order.