Ordering comparisons

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Tue Mar 7 09:54:09 PST 2017


On Mon, Mar 06, 2017 at 08:27:56PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:
> While reviewing work on array comparisons, Vladimir found an odd issue:
> 
> https://issues.dlang.org/show_bug.cgi?id=17244
> 
> Investigation reveals that during array comparison for inequality,
> structs are compared by means of memcmp - even if they don't define
> opCmp, and regardless of the types of their fields. This has obvious
> unpleasant consequences:

Couple of points:

(1) I may be remembering wrong, but I thought structs had always been
intended to be compared field-wise?  I remember when working on AA's
that the compiler would emit a default implementation of opEquals that
did member-wise comparisons. I had always assumed that something
similar was done with inequalities... or was that just unfounded
extrapolation?

(2) I didn't realize that arrays allowed inequalities by default, though
in retrospect it does make sense (since we do define string
inequalities, and string are arrays).  But I would have expected that
structs would *not* allow inequalities by default, because it's not
clear that a default ordering relation makes sense for every struct.
Consider for example, a struct representation of a complex number:

	struct Complex { float re, im; }

It would be wrong to assume a default ordering relation on this struct
because the complex numbers do not have a linear ordering.


[...]
> The question is what to do to minimize breakage yet "break the bad
> code".  The most backward-compatible solution is to define opCmp
> automatically to do a field-by-field lexicographical comparison. The
> most radical solution is disable ordering comparisons unless
> explicitly implemented by the user.
[...]

I wouldn't say disabling ordering comparisons is "radical".  In fact, I
think it makes the most sense by assuming the least about the user's
intended semantics for the struct.  Lexicographical ordering by default
makes sense for arrays (e.g., strings), but I don't think it makes sense
for general structs. Without the user stating what his intents are, it
seems unfounded to presume lexicographic ordering by default.  If the
user has a struct of orthogonal information, e.g., name, phone number,
address, there is no reason why changing the order of fields (during
code refactoring, for example) should result in a completely different
ordering just because the language assumes lexicographical ordering by
default.  It's better to make it an error to involve structs in
inequalities if the user didn't explicitly define opCmp, than to
silently accept such comparisons, which are likely to be buggy, and then
have unusual behaviour later when the user reorders fields and a
seemingly unrelated part of the code suddenly begins producing different
output.

I'd say allowing inequalities on structs by default is surprising
behaviour, whereas asking the user to explicitly specify an ordering is
more expected.


T

-- 
If the comments and the code disagree, it's likely that *both* are wrong. -- Christopher


More information about the Digitalmars-d mailing list