January 12, 2016
On Tuesday, 12 January 2016 at 20:52:51 UTC, Timon Gehr wrote:
> On 01/12/2016 07:27 PM, John Colvin wrote:
>> ...
>
>
> struct S{
>     auto opCmp(S rhs){ return float.nan; }
>     bool opEquals(S rhs){ return false; }
> }
>
> unittest{
>     S a,b;
>     assert(!(a==b));
>     assert(!(a<b));
>     assert(!(a<=b));
>     assert(!(a>b));
>     assert(!(a>=b));
> }

Interesting, I'll have to think more about this. Pretty ugly to have to use floating point instructions for every comparison, no matter the actually data, but maybe there's something here...
January 12, 2016
On Tuesday, 12 January 2016 at 20:52:51 UTC, Timon Gehr wrote:
> On 01/12/2016 07:27 PM, John Colvin wrote:
>> ...
>
>
> struct S{
>     auto opCmp(S rhs){ return float.nan; }
>     bool opEquals(S rhs){ return false; }
> }
>
> unittest{
>     S a,b;
>     assert(!(a==b));
>     assert(!(a<b));
>     assert(!(a<=b));
>     assert(!(a>b));
>     assert(!(a>=b));
> }

what about classes and Object.opCmp?
January 12, 2016
On Tuesday, 12 January 2016 at 19:50:57 UTC, Fool wrote:
> On Tuesday, 12 January 2016 at 19:48:35 UTC, Fool wrote:
>> On Tuesday, 12 January 2016 at 19:46:47 UTC, John Colvin wrote:
>>> On Tuesday, 12 January 2016 at 19:44:18 UTC, Fool wrote:
>>>> Non-reflexive '<=' does not make any sense at all.
>>>
>>> It might be a bit of a mess, agreed, but nonetheless:
>>>
>>> assert(!(float.nan <= float.nan));
>>
>> Agreed, but in case of float '<=' is not an order at all.
>
> By the way, that implies that the result of sorting an array of float by default comparison is undefined unless the array does not contain NaN.

Didn't think of that. Yikes. Should we change the default predicate of std.algorithm.sort to std.math.cmp when ElementType!R is floating point?
January 12, 2016
On Tuesday, 12 January 2016 at 20:56:41 UTC, John Colvin wrote:
> Please consider the second design I proposed? It's small, simple, has no impact on existing code and works in the right direction (library types can emulate / act as replacements for builtins) as opposed to the other way (library types are second class).

If non-total ordering is going to be supported, I don't understand what's wrong with just allowing this:

    bool opCmp(string op, T)(T right) const { }

As an alternative to the current:

    bool opEquals(T)(T right) const { }
    int opCmp(T)(T right) const { }

Make it a compile-time error for a type to implement both. There is no need to deprecate the current system - people can even be encouraged to continue using it, in the very common case where it can actually express the desired logic.

This approach is simple and breaks no existing code. It is also optimally efficient with respect to runtime performance.
January 12, 2016
On Tuesday, 12 January 2016 at 21:06:40 UTC, John Colvin wrote:
> On Tuesday, 12 January 2016 at 19:50:57 UTC, Fool wrote:
>> By the way, that implies that the result of sorting an array of float by default comparison is undefined unless the array does not contain NaN.
>
> Didn't think of that. Yikes. Should we change the default predicate of std.algorithm.sort to std.math.cmp when ElementType!R is floating point?

That depends on whether marketing decides to emphasize safety over performance.

I'm glad that I'm not in charge! ;-)
January 12, 2016
On Tuesday, 12 January 2016 at 21:12:08 UTC, tsbockman wrote:
> On Tuesday, 12 January 2016 at 20:56:41 UTC, John Colvin wrote:
>> Please consider the second design I proposed? It's small, simple, has no impact on existing code and works in the right direction (library types can emulate / act as replacements for builtins) as opposed to the other way (library types are second class).
>
> If non-total ordering is going to be supported, I don't understand what's wrong with just allowing this:
>
>     bool opCmp(string op, T)(T right) const { }
>
> As an alternative to the current:
>
>     bool opEquals(T)(T right) const { }
>     int opCmp(T)(T right) const { }
>
> Make it a compile-time error for a type to implement both. There is no need to deprecate the current system - people can even be encouraged to continue using it, in the very common case where it can actually express the desired logic.
>
> This approach is simple and breaks no existing code. It is also optimally efficient with respect to runtime performance.

I would kindof like that (it would definitely allow me to do what I want, as well as anything else I have failed to notice I need yet), but it flies quite strongly against Walter's (and mine to some extent) views that we'll only end up with C++-like abuse of the overloading if we allow that. Having > and < overloaded separately is asking for trouble.

Another possibility would be to introduce opCmpEquals(T)(T rhs) to handle [<>]= explicitly.
January 12, 2016
On 01/12/2016 10:02 PM, John Colvin wrote:
> On Tuesday, 12 January 2016 at 20:52:51 UTC, Timon Gehr wrote:
>> On 01/12/2016 07:27 PM, John Colvin wrote:
>>> ...
>>
>>
>> struct S{
>>     auto opCmp(S rhs){ return float.nan; }
>>     bool opEquals(S rhs){ return false; }
>> }
>>
>> unittest{
>>     S a,b;
>>     assert(!(a==b));
>>     assert(!(a<b));
>>     assert(!(a<=b));
>>     assert(!(a>b));
>>     assert(!(a>=b));
>> }
>
> what about classes and Object.opCmp?

You can introduce a new opCmp signature in your subclass, but == is enforced to be reflexive for class objects. So this approach only really works for structs. (And for structs, it is obviously a hack.)
January 12, 2016
On 01/12/2016 04:06 PM, John Colvin wrote:
> On Tuesday, 12 January 2016 at 19:50:57 UTC, Fool wrote:
>> On Tuesday, 12 January 2016 at 19:48:35 UTC, Fool wrote:
>>> On Tuesday, 12 January 2016 at 19:46:47 UTC, John Colvin wrote:
>>>> On Tuesday, 12 January 2016 at 19:44:18 UTC, Fool wrote:
>>>>> Non-reflexive '<=' does not make any sense at all.
>>>>
>>>> It might be a bit of a mess, agreed, but nonetheless:
>>>>
>>>> assert(!(float.nan <= float.nan));
>>>
>>> Agreed, but in case of float '<=' is not an order at all.
>>
>> By the way, that implies that the result of sorting an array of float
>> by default comparison is undefined unless the array does not contain NaN.
>
> Didn't think of that. Yikes. Should we change the default predicate of
> std.algorithm.sort to std.math.cmp when ElementType!R is floating point?

We're fine as we are. By default sort compares with "<". -- Andrei
January 12, 2016
On 01/12/2016 03:56 PM, John Colvin wrote:
> Please consider the second design I proposed?

I don't think it solves a large problem. -- Andrei

January 12, 2016
On Tuesday, 12 January 2016 at 22:28:13 UTC, Andrei Alexandrescu wrote:
> On 01/12/2016 03:56 PM, John Colvin wrote:
>> Please consider the second design I proposed?
>
> I don't think it solves a large problem. -- Andrei

Ok. Would you consider any solution, or is that a "leave it broken"?

I think I can find a way around the problem for my purposes in the short term. However, for other people implementing custom types I think it is important, it's a dirty corner that needs sorting out. The more you get to know D, the more of them you find, the more frustrating it gets seeing they aren't likely to get fixed...