recursive equal, and firstDifference functions
Jonathan M Davis
jmdavisProg at gmx.com
Tue Mar 19 20:10:24 PDT 2013
On Wednesday, March 20, 2013 01:17:13 Dan wrote:
> This is true, but then my code is by definition not standard.
> However, theoretically, the language writers could. For example,
> any '==' could be lowered to a 'standard' function, probably
> better named 'intancesDeepEqual(a,b)' and that function could use
> reflection to provide equal when not available else call opEquals
> if it is available. Similar with opCmp, dup, idup, ...
> In other words, in the vein of the original poster, why not allow
> all of these nice goodies (equality comparison, opCmp comparison,
> dup) without requiring boilerplate code while still
> honoring/using it when it is provided.
Okay. I'm going to take a second stab at replying to this, because I think
that I can explain it much better. The standard function that == lowers to is
opEquals. Nothing else is needed. The way that == works is
integral types, char types, pointers, and bool: bitwise comparison
floating point types: equality which is similar to bitwise comparison but takes
NaN into account
arrays: The ptr and length attributes are checked, and if the lengths are
equal but the ptrs are not, then element-wise comparison is used, where each
element is compared with == (whereas if the lengths are different or if the ptr
and length attributes are identical, no further comparison is needed).
structs and classes: Their opEquals is used. If a struct or class does not
define opEquals, then one is generated where each member variable is compared
in turn with ==. So, they are compared recursively.
They _only_ times that you need you need to worry about defining opEquals are
when
1. the default comparison is comparing pointers, and you want to compare what
they point to rather than the pointers themselves.
2. you want equality to mean something other than calling == on each member
variable (including doing something other than == on a particular member
variable as might be the case with a member variable which is a range).
The way == is defined is very clean and straightforward. There _are_ bugs which
complicate things (e.g. http://d.puremagic.com/issues/show_bug.cgi?id=3789 ),
but those can and will be fixed. The design itself is solid.
It's true that equal is often need for comparing ranges of the same type, but
that's arguably a defect in the implementations of those ranges. equal is
specifically designed to compare ranges which are different types but have the
same element type. == is what's for comparing objects of the same type. But
most ranges don't currently define opEquals, even when they need it in order
for it to do a proper comparison. That's arguably something that should be
fixed, but it's a design issue of ranges, not ==. But if you want to ensure
that equal is used, you can always use a mixin to define opEquals that way
(though you actually risk making the comparison less efficient than it would be
if the ranges themselves defined opEquals).
So, I can see a definite argument that ranges should make sure that they define
opEquals (which wouldn't negate the general need for equal as that's
specifically for comparing ranges of different types which have the same element
type), but there's no need to change how == works. The design is actually very
clean.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list