recursive equal, and firstDifference functions

Jonathan M Davis jmdavisProg at gmx.com
Tue Mar 19 17:51:54 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.

There _are_ defaults for ==, and it really does quite a lot for you (e.g. 
recursively using == on each of a type's member variables), so you don't 
always have to define opEquals, but as soon as you have a layer of indirection 
(aside from arrays), you do have to define opEquals, or you'll generally end up 
checking for reference/pointer equality rather than equality of the actual 
objects. And in some cases, that's exactly the right thing to do. In others, 
it's not. It all depends on the context.

As for comparing ranges, it would actually be very bad for performance if they 
defaulted to what equal does (particularly with regards to strings), and the 
language really doesn't do much to support ranges directly. Aside from 
foreach, they're completely a library construct. And really, equal exists with 
the idea that ranges of different types (but the same element type) can be 
compared, which isn't what you're generally trying to do with opEquals at all.

If you want to avoid boilerplate, then use mixins. It should be fairly trivial 
to define a mixin such that you can do something like

mixin(defineOpEquals!(typeof(this)));

which defines an opEquals which does deep comparison. But also remember that 
what is necessary for deep comparison often depends on the types being 
compared (e.g. a range may or may not require equal to get the comparison that 
you want), so while it may be possible to define a mixin which creates an 
opEquals which will work in most situations, there are plenty where it won't. 
For instance, given that the standard library supports ranges, it's likely 
that something like defineOpEquals would know about them and do what is most 
likely to be the correct thing for them, but if ranges weren't part of the 
standard library, thhen defineOpEquals wouldn't know about them and couldn't 
handle them properly. The same will be true for any user-defined type that 
requires a particular idiom in order to be compared correctly.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list