recursive equal, and firstDifference functions
Jonathan M Davis
jmdavisProg at gmx.com
Tue Mar 19 12:07:40 PDT 2013
On Tuesday, March 19, 2013 11:12:38 H. S. Teoh wrote:
> On Tue, Mar 19, 2013 at 01:48:43PM -0400, Jonathan M Davis wrote:
> > On Tuesday, March 19, 2013 18:26:16 timotheecour wrote:
> > > > somewhere else, but I don't see a relevant package. Maybe a new
> > > > std.algorithm2 for non-ranges?
> > > >
> > > > Also, the OT's firstDifference would go there too, and I have a
> > > > recursive (to specified level) toStringRecurse that would
> > > > belong there too.
> > >
> > > Also, I'd add to that list copyRecurse and some more, that
> > > operate on arbitrary types, not just ranges, so we have:
> > >
> > > equalRecurse
> > > copyRecurse (deep copy)
> > > toStringRecurse
> > > firstDifference (see OT)
> > > toHashRecurse (should compare equal with a data structure
> > > serialized and then deserialized via a serialization function, eg
> > > std.orange)
> > >
> > > I'm sure there's more.
> > >
> > > that seems a starting point for a new package that operates on any
> > > type recursively (not just ranges), no? std.deep?std.recurse? Some
> > > of those could have a depth level compile time parameter that stops
> > > recursion at that level, which would be infinity by default.
> >
> > And how do you even have the concept of recursion without some sort of
> > range or container to recursively iterate through?
>
> [...]
>
> One can iterate over every member of a struct/class and recursively
> invoke equalRecurse on them. Something like this:
>
> bool recursiveEqual(T)(T a, T b) {
> static if (isAtomic!T) {
> return a == b;
> } else {
> foreach (attr; __traits(getAllMembers, T)) {
> // TBD: need to skip stuff like member
> // functions or internal stuff like
> // compiler-generated attributes, hidden
> // context ptrs, etc.
>
> alias attr1 = __traits(getMember, a, attr);
> alias attr2 = __traits(getMember, b, attr);
>
> if (!recursiveEqual(attr, attr2))
> return false;
> }
> }
> return true;
> }
True, but that's completely different from what equal does, and it would be
very dangerous IMHO. opEquals is supposed to be handling comparing types
recursively like that. Deciding on your own that a type's member variables
should be compared with equal instead of == risk doing some nasty things to
the semantics of the types that you're dealing with. If a type's member
variables need to be compared with equal, then its opEquals should do that.
equal is for handling the case where you're comparing two arbitrary ranges of
elements. You don't care what the types of the ranges are. You're comparing
the elements, not the ranges. You would only need to recursively compare the
elements with anything other than == if they were ranges, and you wanted to
ultimately compare the elements of the deepest ranges. == already exists to
compare the elements themselves recursively.
I'd strongly argue that a function like the one that you just gave is an
extremely bad idea. It's trying to implement == for a type. Let the type define
that for itself like it's supposed to.
- jonathan M Davis
More information about the Digitalmars-d-learn
mailing list