ProtoObject and comparison for equality and ordering

H. S. Teoh hsteoh at quickfur.ath.cx
Wed May 15 16:52:14 UTC 2019


On Wed, May 15, 2019 at 09:56:53AM +0100, Steven Schveighoffer via Digitalmars-d wrote:
> On 5/14/19 9:36 PM, Eduard Staniloiu wrote:
> > Jonathan's question got us to the point raised: maybe it doesn't
> > make much sense to be able to compare two `ProtoObjects`, so maybe
> > you shouldn't be able to. This would change the interface to
> > ```
> > interface Ordered(T)
> > {
> >      int opCmp(scope const T rhs);
> > }
> > ```
> > 
> > Now the attributes of `opCmp` will be inferred.
> 
> Just wanted to make sure you understand this is not the case. opCmp in
> this instance is a virtual call, and will NOT have attributes
> inferred.
> 
> There isn't really a way to define an interface for this, nor do you
> need to.
> 
> Just define the opCmp you want in your own interface/base object, and
> then you can compare those. Almost nobody wants to compare 2
> completely unrelated objects.
[...]

+1.  *This* is the right way to go.  Forget about using interfaces or
other such inferior hacks; D has powerful compile-time introspection,
why aren't we taking full advantage of it??  Let the user define their
own base class (or interface) with whatever definition of opCmp they
wish to have. This solves a host of issues:

1) How to define opCmp in a way that satisfies everyone: some people
want int opCmp, some want float opCmp, etc.. Why make the decision for
them? Let them decide themselves which version their opCmp wants. Pass
the buck to the user.

2) How to attribute opCmp in a non-restrictive way: pass the buck to the
user.

3) How to compare two ProtoObjects?  If the user wants to compare two
disparate objects, let them define their own common base class with an
appropriate version of opCmp. Pass the buck to the user.

4) What if this doesn't work? (I.e., the user has two objects from two
completely unrelated, opaque, binary-only libraries whose opCmp's are
not compatible with each other.)  Easy, you already know nothing about
the two objects, and since they are related they don't have any
meaningfully-comparable state anyway, so just wrap them in a struct
whose opCmp just compares their respective pointer values:

	struct ComparableProtoObject {
		ProtoObject payload;
		int opCmp(in ComparableProtoObject o) @trusted {
			auto a = cast(void*)payload;
			auto b = cast(void*)o.payload;
			return (a < b) ? -1 : (a > b) ? 1 : 0;
		}
	}

IOW, pass the buck to the user.

4) What about inheritance? See (2).  Pass the buck to the user.

5) What about AA's?  For something to be hashable, you need .toHash,
.opEquals, and perhaps .opCmp (depending on whether the AA's buckets
needs stuff to be orderable).  So either the user creates a Hashable
interface for their objects with appropriate definitions of toHash,
opEquals, and opCmp, or see (4). IOW, pass the buck to the user.


The user is not an idiot; give him the tools to do what he wants instead
of making decisions for him and handing it down from on high.


T

-- 
This sentence is false.


More information about the Digitalmars-d mailing list