View mode: basic / threaded / horizontal-split · Log in · Help
September 13, 2004
Round-up of the excuses for keeping Object.opCmp, and rebuttals to them
1. "It's needed for associative arrays to work."

Firstly, this is implementation-specific.  There's no need for AAs to be 
implemented in terms of Object.opCmp, or to rely on an ordering 
comparator at all.  True, an ordering can make AAs more efficient, but 
only where one exists.  If anything, then in the current state 
Object.opCmp is _preventing_ AAs from working on classes that have no 
ordering.

2. "How else can an array of objects be sorted?"

Objects of diverse classes aren't going to be mutually comparable.  Of 
course, one might want to design two or more classes with comparability 
between them.  But if that's the case, then they would derive from some 
common base class or interface that defines the scope of mutual 
comparability.  Then sorting an Object[] doesn't make sense, but sorting 
an array of the common base class does.

3. "Putting it in Object reserves a predictable vtbl[] slot for it."

If everything (e.g. array aggregate properties when/if we get them) 
followed the implementation pattern of AAs and sort, then we would end 
up with a lot of vtbl slots reserved for operators that tend to do 
nothing, and even more coding errors to slip through the compiler to the 
runtime.

Even if there's some reason to keep AAs and sort to use this mechanism, 
rather than reimplementing them by templates, then reserving a 
predictable vtbl slot doesn't need to be done by actually filling it. 
It could be done simply by specifying a slot to be reserved in the ABI. 
 In Object, this slot would be set to null, and the compiler would fill 
it only when a class Qwert defines an opCmp(Qwert).

Of course, if you then have something like

    class Yuiop : Qwert {
        int opCmp(Qwert q) { ... }

        int opCmp(Yuiop y) { ... }
    }

then the first form would override.  This makes sense, as it only makes 
sense for Yuiop.opCmp(Qwert) to call Yuiop.opCmp(Yuiop) if the argument 
is a Yuiop.  Then we have a principle: the reserved slot would carry the 
form of opCmp that reflects the scope of mutual comparability.  Hence 
Yuiop[].sort and Qwert[].sort would behave identically, and consistently 
with uses of the comparison operators directly (under current rules) 
regardless of which types are declared.

Then, when an AA is declared of a certain class as keytype, the compiler 
would look in that class's vtbl to see if the opCmp slot is set to null; 
in which case, it would hook up an AA implementation that doesn't rely 
on opCmp.  Similarly, when sort is called on an array, the compiler 
would report an error if opCmp is null.


Maybe some other excuses have been brought up before, but I can't think 
of them.  Is there anything to add to this list?

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
September 13, 2004
Re: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them
"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message
news:ci46lq$19k0$1@digitaldaemon.com...
> 1. "It's needed for associative arrays to work."
>
> Firstly, this is implementation-specific.  There's no need for AAs to be
> implemented in terms of Object.opCmp, or to rely on an ordering
> comparator at all.  True, an ordering can make AAs more efficient, but
> only where one exists.  If anything, then in the current state
> Object.opCmp is _preventing_ AAs from working on classes that have no
> ordering.
>
> 2. "How else can an array of objects be sorted?"
>
> Objects of diverse classes aren't going to be mutually comparable.  Of
> course, one might want to design two or more classes with comparability
> between them.  But if that's the case, then they would derive from some
> common base class or interface that defines the scope of mutual
> comparability.  Then sorting an Object[] doesn't make sense, but sorting
> an array of the common base class does.
>
> 3. "Putting it in Object reserves a predictable vtbl[] slot for it."
>
> If everything (e.g. array aggregate properties when/if we get them)
> followed the implementation pattern of AAs and sort, then we would end
> up with a lot of vtbl slots reserved for operators that tend to do
> nothing, and even more coding errors to slip through the compiler to the
> runtime.
>
> Even if there's some reason to keep AAs and sort to use this mechanism,
> rather than reimplementing them by templates, then reserving a
> predictable vtbl slot doesn't need to be done by actually filling it.
> It could be done simply by specifying a slot to be reserved in the ABI.
>   In Object, this slot would be set to null, and the compiler would fill
> it only when a class Qwert defines an opCmp(Qwert).
>
> Of course, if you then have something like
>
>      class Yuiop : Qwert {
>          int opCmp(Qwert q) { ... }
>
>          int opCmp(Yuiop y) { ... }
>      }
>
> then the first form would override.  This makes sense, as it only makes
> sense for Yuiop.opCmp(Qwert) to call Yuiop.opCmp(Yuiop) if the argument
> is a Yuiop.  Then we have a principle: the reserved slot would carry the
> form of opCmp that reflects the scope of mutual comparability.  Hence
> Yuiop[].sort and Qwert[].sort would behave identically, and consistently
> with uses of the comparison operators directly (under current rules)
> regardless of which types are declared.
>
> Then, when an AA is declared of a certain class as keytype, the compiler
> would look in that class's vtbl to see if the opCmp slot is set to null;
> in which case, it would hook up an AA implementation that doesn't rely
> on opCmp.  Similarly, when sort is called on an array, the compiler
> would report an error if opCmp is null.
>
>
> Maybe some other excuses have been brought up before, but I can't think
> of them.  Is there anything to add to this list?

A very nice post! And a great illustration of problems that opCmp causes
:)

> Stewart.
>
> --
> My e-mail is valid but not my primary mailbox.  Please keep replies on
> the 'group where everyone may benefit.
September 13, 2004
Re: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them
"excuses"? that's a pretty heavy word to use.

More to the point, Walter knows the TypeInfo system needs more bake-time.
opCmp is crucial to Object's TypeInfo. So any proposal to remove opCmp needs
to include a proposal to modify the TypeInfo for Object or to modify the
TypeInfo system generally. I don't know the details about how the compiler
manages TypeInfos (I know there are a bunch in std/typeinfo but I don't know
if the compiler looks at that code during compiling or only at link time).
Since the TypeInfo existed before templates I wouldn't be surprised if some
parts of TypeInfo can be removed - but it would probably take non-trivial
compiler changes. I don't know if Walter is going to take the time to step
back and look at TypeInfos before 1.0.

"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message
news:ci46lq$19k0$1@digitaldaemon.com...
> 1. "It's needed for associative arrays to work."
>
> Firstly, this is implementation-specific.  There's no need for AAs to be
> implemented in terms of Object.opCmp, or to rely on an ordering
> comparator at all.  True, an ordering can make AAs more efficient, but
> only where one exists.  If anything, then in the current state
> Object.opCmp is _preventing_ AAs from working on classes that have no
> ordering.
>
> 2. "How else can an array of objects be sorted?"
>
> Objects of diverse classes aren't going to be mutually comparable.  Of
> course, one might want to design two or more classes with comparability
> between them.  But if that's the case, then they would derive from some
> common base class or interface that defines the scope of mutual
> comparability.  Then sorting an Object[] doesn't make sense, but sorting
> an array of the common base class does.
>
> 3. "Putting it in Object reserves a predictable vtbl[] slot for it."
>
> If everything (e.g. array aggregate properties when/if we get them)
> followed the implementation pattern of AAs and sort, then we would end
> up with a lot of vtbl slots reserved for operators that tend to do
> nothing, and even more coding errors to slip through the compiler to the
> runtime.
>
> Even if there's some reason to keep AAs and sort to use this mechanism,
> rather than reimplementing them by templates, then reserving a
> predictable vtbl slot doesn't need to be done by actually filling it.
> It could be done simply by specifying a slot to be reserved in the ABI.
>   In Object, this slot would be set to null, and the compiler would fill
> it only when a class Qwert defines an opCmp(Qwert).
>
> Of course, if you then have something like
>
>      class Yuiop : Qwert {
>          int opCmp(Qwert q) { ... }
>
>          int opCmp(Yuiop y) { ... }
>      }
>
> then the first form would override.  This makes sense, as it only makes
> sense for Yuiop.opCmp(Qwert) to call Yuiop.opCmp(Yuiop) if the argument
> is a Yuiop.  Then we have a principle: the reserved slot would carry the
> form of opCmp that reflects the scope of mutual comparability.  Hence
> Yuiop[].sort and Qwert[].sort would behave identically, and consistently
> with uses of the comparison operators directly (under current rules)
> regardless of which types are declared.
>
> Then, when an AA is declared of a certain class as keytype, the compiler
> would look in that class's vtbl to see if the opCmp slot is set to null;
> in which case, it would hook up an AA implementation that doesn't rely
> on opCmp.  Similarly, when sort is called on an array, the compiler
> would report an error if opCmp is null.
>
>
> Maybe some other excuses have been brought up before, but I can't think
> of them.  Is there anything to add to this list?
>
> Stewart.
>
> -- 
> My e-mail is valid but not my primary mailbox.  Please keep replies on
> the 'group where everyone may benefit.
September 14, 2004
Re: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them
Ben Hinkle wrote:

> "excuses"? that's a pretty heavy word to use.
> 
> More to the point, Walter knows the TypeInfo system needs more bake-time.
> opCmp is crucial to Object's TypeInfo. So any proposal to remove opCmp needs
> to include a proposal to modify the TypeInfo for Object or to modify the
> TypeInfo system generally.
<snip top of upside-down reply>

LTIK, the plan was to have class-specific TypeInfos - this is already a 
shortcoming in a handful of respects.  But yes, you have a point.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
March 09, 2005
A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]
First of all, I have to say that I think the whole idea of opCmp, and 
any similar things involving/requiring Object references and casts, 
stinks. I don't have to do any of this kind of crap in C++ to achieve 
all manner of efficient and generic manipulation. One has to to it in 
Java/.NET, but then .... <editor: censored for being rude and 
repetitive> ... which D claims to be an evolution from.

Specific responses (and the occasional gripe) within.

"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message 
news:ci46lq$19k0$1@digitaldaemon.com...
> 1. "It's needed for associative arrays to work."
>
> Firstly, this is implementation-specific.  There's no need for AAs to 
> be implemented in terms of Object.opCmp, or to rely on an ordering 
> comparator at all.  True, an ordering can make AAs more efficient, but 
> only where one exists.  If anything, then in the current state 
> Object.opCmp is _preventing_ AAs from working on classes that have no 
> ordering.

Since AAs are built-in, why on earth do they need to rely on runtime 
polymorphism. Given the classes X and Y

class X
{
}

class Y
{
   int opCmp(Y rhs);
}

What prevents the compiler from generating sorting based on arbitrary 
difference (e.g. address of instance) for X, and using the 
*non-polymorphic* Y::opCmp(Y) ?? (I know all methods are polymorphic in 
D, but

> 2. "How else can an array of objects be sorted?"

Why should an array of arbitrary types be sortable??

For example, suppose I have an array of PGP keys, or MD5 hashes. In what 
way could one define a meaningful ordering relation? (Naturally one can 
go lexicographical, but that's an arbitrary choice. Might as well order 
on which one contains the longest character sub-sequence of the word 
"Churlish" within them.)

If anyone truly wants to be able to meaningfully sort a Chair, a 
Weather, an Md5Sum, and a Vector object held in an array, then they need 
to strap on the latex and go wibble!

Sorting of Object is utterly bogus, and should be immediately dispensed 
with. (However, polymorphic sorting is not necessarily wrong .... )

> Objects of diverse classes aren't going to be mutually comparable.

Abso-stinkingly-lutely not!!

It's really easy. For polymorphic classes, such as the following, one 
can easily support comparison:


class Base
{
   int opCmp(Base);    // NOTE: param is Base
}

class Derived
   : public Base
{
}

class MoreDerived
   : public Derived
{
}

As it stands above, a heterogeneous array of instances of these types, 
say [b1, b2, d1, md1, b3, md2, b4] would be sortable because Base 
derives opCmp(). Moreover, it would be sorted solely by the 
implementation of Base.opCmp() for all instances irrespective of their 
actual type.

   Base[]    ba =    [b1, b2, d1, md1, b3, md2, b4];

   ba.sort; // Calls Base.opCmp(Base)

Similarly, an array of Derived (and MoreDerived) would also sort using 
Base.opCmp().

   Derived[]  da = [d1, md1, md2]

   da.sort; // Calls Base.opCmp(Base)

Now consider that the author of MoreDerived knows - and being the author 
of the class, he/she's the one that will know - that they need to 
override the sorting logic for sorting of non-heterogeneous arrays of 
MoreDerived instances. (Actually, it's not "non-heterogeneous arrays of 
MoreDerived instances." In fact, it's "Arrays of MoreDerived (and any 
class derived from MoreDerived).") All he/she does is define an 
_overload_, opCmp(MoreDerived)

class MoreDerived
   : public Derived
{
   int opCmp(MoreDerived); // Note: param is MoreDerived
}

MoreDerived mda = [md1, md2]

mda.sort; // Calls MoreDerived.opCmp(MoreDerived)


Now, when the compiler is generating the code to sort an array on 
MoreDerived, it will implement it in terms of 
MoreDerived.opCmp(MoreDerived). It will do _nothing_ with Base.opCmp(). 
Indeed, if the author of Base was to remove Base.opCmp(Base), rendering 
the lines "ba.sort;" and "da.sort;" as compile errors, the line 
"mda.sort;" would be entirely unaffected and would remain legal.

Now consider that the author of Derived wants to override opCmp(Base), 
in order to something a little smarter when involved in Base sorting. 
Now "ba.sort;" will use both Base.opCmp(Base) and Derived.opCmp(Base). 
That's perfectly right, because MoreDerived, as a child of Derived that 
has _not_ overrident opCmp(Base), is implicitly defined to be happy with 
what Derived does when Base sorting. (Child-Base coupling fragility 
necessarily applies here, of course, but that's an artefact of OO, and 
nothing to do with the ramifications of this proposal.) The important 
thing is that this amendment to the hierarchy does not affect 
"mda.sort;" one whit. It still uses MoreDerived.sort(MoreDerived).

In practical terms, the issues of what-actually-happens-in-the-sort and 
comparing-with-same-type-or-base-type will remain as they do in current 
OO hierarchies. The important distinction between this and the current 
situation is that the compiler sorts using the deepest opCmp() available 
for all types in the array. (I've not considered what other sorting 
arrangements we might consider, but I suspect that polymorphism will 
resolve to the deepest one in sorting template containers, doing what I 
propose for the compiler do as a natural part of runtime polymorphism. 
Which is nice. <g>)

Since a corollary stipulation is that comparison will only be allowed 
(_at_compile_time_ !! Hurrah!!!) for types for which it is sensible to 
do so - i.e. those that are polymorphically related from a common 
non-root subtree of the class hierarchy and have, in a common ancestor, 
an opCmp defined - we'd totally avoid all that evil 
is-rhs-same-type-if-not-throw guff.

In a sense, this would be like the IComparable stuff, but for the fact 
that any shared parent that sports an opCmp can act as such an 
'interface', without the attendant hassles of a prescribed interface.

I respectfully submit that this proposal completely obviates the need 
for opCmp as far as arrays are concerned and, in addition, affords us 
the opportunity to tighted up type resolution at compile time. All 
without costing us any flexibility. (There may, of course, be unforeseen 
drawbacks, as I'm less omniscient than I was ...)

> 3. "Putting it in Object reserves a predictable vtbl[] slot for it."
>
> If everything (e.g. array aggregate properties when/if we get them) 
> followed the implementation pattern of AAs and sort, then we would end 
> up with a lot of vtbl slots reserved for operators that tend to do 
> nothing, and even more coding errors to slip through the compiler to 
> the runtime.

Agreed. Why not have a vtbl[] slot for everthing: serialisation, 
sorting, stringising, etc. etc. etc.

In a modern language with powerful generic facilities - templates, shims 
(if we ever devise the way to do these in D), interfaces, mixins, etc. - 
why do we need to put on such straight jackets?

(That question's not entirely rhetorical. If there is a genuine reason 
that benefits the user, and not just the implementor, then I'm very 
interested to hear it.)

> Even if there's some reason to keep AAs and sort to use this 
> mechanism, rather than reimplementing them by templates, then 
> reserving a predictable vtbl slot doesn't need to be done by actually 
> filling it. It could be done simply by specifying a slot to be 
> reserved in the ABI. In Object, this slot would be set to null, and 
> the compiler would fill it only when a class Qwert defines an 
> opCmp(Qwert).

True, but that's now something that sucks 50% rather than 100%. Let's 
get 0.

> Of course, if you then have something like
>
>     class Yuiop : Qwert {
>         int opCmp(Qwert q) { ... }
>
>         int opCmp(Yuiop y) { ... }
>     }
>
> then the first form would override.  This makes sense, as it only 
> makes sense for Yuiop.opCmp(Qwert) to call Yuiop.opCmp(Yuiop) if the 
> argument is a Yuiop.  Then we have a principle: the reserved slot 
> would carry the form of opCmp that reflects the scope of mutual 
> comparability.  Hence Yuiop[].sort and Qwert[].sort would behave 
> identically, and consistently with uses of the comparison operators 
> directly (under current rules) regardless of which types are declared.
>
> Then, when an AA is declared of a certain class as keytype, the 
> compiler would look in that class's vtbl to see if the opCmp slot is 
> set to null; in which case, it would hook up an AA implementation that 
> doesn't rely on opCmp.  Similarly, when sort is called on an array, 
> the compiler would report an error if opCmp is null.

Hmmm. This seems somewhat similar to my proposal above, apart from the 
slot business (which I say has no business being a concern) - maybe I 
should have read all your post before starting my reply. <CG>

Seriously, though, the fact that two people have come up with a similar 
idea for kicking opCmp() out of where it has no business being gives 
some encouragement, methinks.

> Maybe some other excuses have been brought up before, but I can't 
> think of them.  Is there anything to add to this list?

Since your post elicited little response in September, we must surmise 
that there are none.

Walter, I commend this idea for your sincerest consideration.

:-)

Matthew
March 09, 2005
Re: A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]
Matthew, may I translate your proposal(?)(below) into this:

"opCmp based array sort is bad.
It does not support runtime polymorphism. We need to change this"
Am I right?

I've attached simple template (with example)

template sort(T)
{
 void sort(T[] arr, int function(in T l, in T r) cmp) {...}
}

used as:

int arr[] = new int[10000];
sort!(int) ( arr,   function int(int i1,int i2) { return i1 - i2; }    );

It is simple and works *30% faster* than D builtin sort. Walter, please, pay 
attention - C standard qsort is a piece of...

Andrew Fedoniouk.
http://terrainformatica.com

"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message 
news:d0lsv5$1496$1@digitaldaemon.com...
> First of all, I have to say that I think the whole idea of opCmp, and
> any similar things involving/requiring Object references and casts,
> stinks. I don't have to do any of this kind of crap in C++ to achieve
> all manner of efficient and generic manipulation. One has to to it in
> Java/.NET, but then .... <editor: censored for being rude and
> repetitive> ... which D claims to be an evolution from.
>
> Specific responses (and the occasional gripe) within.
>
> "Stewart Gordon" <smjg_1998@yahoo.com> wrote in message
> news:ci46lq$19k0$1@digitaldaemon.com...
>> 1. "It's needed for associative arrays to work."
>>
>> Firstly, this is implementation-specific.  There's no need for AAs to
>> be implemented in terms of Object.opCmp, or to rely on an ordering
>> comparator at all.  True, an ordering can make AAs more efficient, but
>> only where one exists.  If anything, then in the current state
>> Object.opCmp is _preventing_ AAs from working on classes that have no
>> ordering.
>
> Since AAs are built-in, why on earth do they need to rely on runtime
> polymorphism. Given the classes X and Y
>
> class X
> {
> }
>
> class Y
> {
>    int opCmp(Y rhs);
> }
>
> What prevents the compiler from generating sorting based on arbitrary
> difference (e.g. address of instance) for X, and using the
> *non-polymorphic* Y::opCmp(Y) ?? (I know all methods are polymorphic in
> D, but
>
>> 2. "How else can an array of objects be sorted?"
>
> Why should an array of arbitrary types be sortable??
>
> For example, suppose I have an array of PGP keys, or MD5 hashes. In what
> way could one define a meaningful ordering relation? (Naturally one can
> go lexicographical, but that's an arbitrary choice. Might as well order
> on which one contains the longest character sub-sequence of the word
> "Churlish" within them.)
>
> If anyone truly wants to be able to meaningfully sort a Chair, a
> Weather, an Md5Sum, and a Vector object held in an array, then they need
> to strap on the latex and go wibble!
>
> Sorting of Object is utterly bogus, and should be immediately dispensed
> with. (However, polymorphic sorting is not necessarily wrong .... )
>
>> Objects of diverse classes aren't going to be mutually comparable.
>
> Abso-stinkingly-lutely not!!
>
> It's really easy. For polymorphic classes, such as the following, one
> can easily support comparison:
>
>
> class Base
> {
>    int opCmp(Base);    // NOTE: param is Base
> }
>
> class Derived
>    : public Base
> {
> }
>
> class MoreDerived
>    : public Derived
> {
> }
>
> As it stands above, a heterogeneous array of instances of these types,
> say [b1, b2, d1, md1, b3, md2, b4] would be sortable because Base
> derives opCmp(). Moreover, it would be sorted solely by the
> implementation of Base.opCmp() for all instances irrespective of their
> actual type.
>
>    Base[]    ba =    [b1, b2, d1, md1, b3, md2, b4];
>
>    ba.sort; // Calls Base.opCmp(Base)
>
> Similarly, an array of Derived (and MoreDerived) would also sort using
> Base.opCmp().
>
>    Derived[]  da = [d1, md1, md2]
>
>    da.sort; // Calls Base.opCmp(Base)
>
> Now consider that the author of MoreDerived knows - and being the author
> of the class, he/she's the one that will know - that they need to
> override the sorting logic for sorting of non-heterogeneous arrays of
> MoreDerived instances. (Actually, it's not "non-heterogeneous arrays of
> MoreDerived instances." In fact, it's "Arrays of MoreDerived (and any
> class derived from MoreDerived).") All he/she does is define an
> _overload_, opCmp(MoreDerived)
>
> class MoreDerived
>    : public Derived
> {
>    int opCmp(MoreDerived); // Note: param is MoreDerived
> }
>
> MoreDerived mda = [md1, md2]
>
> mda.sort; // Calls MoreDerived.opCmp(MoreDerived)
>
>
> Now, when the compiler is generating the code to sort an array on
> MoreDerived, it will implement it in terms of
> MoreDerived.opCmp(MoreDerived). It will do _nothing_ with Base.opCmp().
> Indeed, if the author of Base was to remove Base.opCmp(Base), rendering
> the lines "ba.sort;" and "da.sort;" as compile errors, the line
> "mda.sort;" would be entirely unaffected and would remain legal.
>
> Now consider that the author of Derived wants to override opCmp(Base),
> in order to something a little smarter when involved in Base sorting.
> Now "ba.sort;" will use both Base.opCmp(Base) and Derived.opCmp(Base).
> That's perfectly right, because MoreDerived, as a child of Derived that
> has _not_ overrident opCmp(Base), is implicitly defined to be happy with
> what Derived does when Base sorting. (Child-Base coupling fragility
> necessarily applies here, of course, but that's an artefact of OO, and
> nothing to do with the ramifications of this proposal.) The important
> thing is that this amendment to the hierarchy does not affect
> "mda.sort;" one whit. It still uses MoreDerived.sort(MoreDerived).
>
> In practical terms, the issues of what-actually-happens-in-the-sort and
> comparing-with-same-type-or-base-type will remain as they do in current
> OO hierarchies. The important distinction between this and the current
> situation is that the compiler sorts using the deepest opCmp() available
> for all types in the array. (I've not considered what other sorting
> arrangements we might consider, but I suspect that polymorphism will
> resolve to the deepest one in sorting template containers, doing what I
> propose for the compiler do as a natural part of runtime polymorphism.
> Which is nice. <g>)
>
> Since a corollary stipulation is that comparison will only be allowed
> (_at_compile_time_ !! Hurrah!!!) for types for which it is sensible to
> do so - i.e. those that are polymorphically related from a common
> non-root subtree of the class hierarchy and have, in a common ancestor,
> an opCmp defined - we'd totally avoid all that evil
> is-rhs-same-type-if-not-throw guff.
>
> In a sense, this would be like the IComparable stuff, but for the fact
> that any shared parent that sports an opCmp can act as such an
> 'interface', without the attendant hassles of a prescribed interface.
>
> I respectfully submit that this proposal completely obviates the need
> for opCmp as far as arrays are concerned and, in addition, affords us
> the opportunity to tighted up type resolution at compile time. All
> without costing us any flexibility. (There may, of course, be unforeseen
> drawbacks, as I'm less omniscient than I was ...)
>
>> 3. "Putting it in Object reserves a predictable vtbl[] slot for it."
>>
>> If everything (e.g. array aggregate properties when/if we get them)
>> followed the implementation pattern of AAs and sort, then we would end
>> up with a lot of vtbl slots reserved for operators that tend to do
>> nothing, and even more coding errors to slip through the compiler to
>> the runtime.
>
> Agreed. Why not have a vtbl[] slot for everthing: serialisation,
> sorting, stringising, etc. etc. etc.
>
> In a modern language with powerful generic facilities - templates, shims
> (if we ever devise the way to do these in D), interfaces, mixins, etc. -
> why do we need to put on such straight jackets?
>
> (That question's not entirely rhetorical. If there is a genuine reason
> that benefits the user, and not just the implementor, then I'm very
> interested to hear it.)
>
>> Even if there's some reason to keep AAs and sort to use this
>> mechanism, rather than reimplementing them by templates, then
>> reserving a predictable vtbl slot doesn't need to be done by actually
>> filling it. It could be done simply by specifying a slot to be
>> reserved in the ABI. In Object, this slot would be set to null, and
>> the compiler would fill it only when a class Qwert defines an
>> opCmp(Qwert).
>
> True, but that's now something that sucks 50% rather than 100%. Let's
> get 0.
>
>> Of course, if you then have something like
>>
>>     class Yuiop : Qwert {
>>         int opCmp(Qwert q) { ... }
>>
>>         int opCmp(Yuiop y) { ... }
>>     }
>>
>> then the first form would override.  This makes sense, as it only
>> makes sense for Yuiop.opCmp(Qwert) to call Yuiop.opCmp(Yuiop) if the
>> argument is a Yuiop.  Then we have a principle: the reserved slot
>> would carry the form of opCmp that reflects the scope of mutual
>> comparability.  Hence Yuiop[].sort and Qwert[].sort would behave
>> identically, and consistently with uses of the comparison operators
>> directly (under current rules) regardless of which types are declared.
>>
>> Then, when an AA is declared of a certain class as keytype, the
>> compiler would look in that class's vtbl to see if the opCmp slot is
>> set to null; in which case, it would hook up an AA implementation that
>> doesn't rely on opCmp.  Similarly, when sort is called on an array,
>> the compiler would report an error if opCmp is null.
>
> Hmmm. This seems somewhat similar to my proposal above, apart from the
> slot business (which I say has no business being a concern) - maybe I
> should have read all your post before starting my reply. <CG>
>
> Seriously, though, the fact that two people have come up with a similar
> idea for kicking opCmp() out of where it has no business being gives
> some encouragement, methinks.
>
>> Maybe some other excuses have been brought up before, but I can't
>> think of them.  Is there anything to add to this list?
>
> Since your post elicited little response in September, we must surmise
> that there are none.
>
> Walter, I commend this idea for your sincerest consideration.
>
> :-)
>
> Matthew
>
>
March 09, 2005
Re: A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]
Matthew wrote:
<snip>
> Since AAs are built-in, why on earth do they need to rely on runtime 
> polymorphism. Given the classes X and Y
> 
> class X
> {
> }
> 
> class Y
> {
>     int opCmp(Y rhs);
> }
> 
> What prevents the compiler from generating sorting based on arbitrary 
> difference (e.g. address of instance) for X, and using the 
> *non-polymorphic* Y::opCmp(Y) ?? (I know all methods are polymorphic in 
> D, but

What would be the purpose of making address of instance the default 
sorting key?  Surely sorting an array of X would be a compiler error.

>>2. "How else can an array of objects be sorted?"
> 
> Why should an array of arbitrary types be sortable??
<snip>

That's exactly my point.  It makes no sense.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
March 09, 2005
Re: A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]
"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message 
news:d0mhe2$1rsr$1@digitaldaemon.com...
> Matthew wrote:
> <snip>
>> Since AAs are built-in, why on earth do they need to rely on runtime 
>> polymorphism. Given the classes X and Y
>>
>> class X
>> {
>> }
>>
>> class Y
>> {
>>     int opCmp(Y rhs);
>> }
>>
>> What prevents the compiler from generating sorting based on arbitrary 
>> difference (e.g. address of instance) for X, and using the 
>> *non-polymorphic* Y::opCmp(Y) ?? (I know all methods are polymorphic 
>> in D, but
>
> What would be the purpose of making address of instance the default 
> sorting key?  Surely sorting an array of X would be a compiler error.

For AAs, not for arrays. Sorting an array of X would be a compiler 
error.

>>>2. "How else can an array of objects be sorted?"
>>
>> Why should an array of arbitrary types be sortable??
> <snip>
>
> That's exactly my point.  It makes no sense.

Mine too. :-)
March 09, 2005
Re: A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]
>I've attached simple template (with example)
>
>template sort(T)
>{
>  void sort(T[] arr, int function(in T l, in T r) cmp) {...}
>}
>
>used as:
>
>int arr[] = new int[10000];
>sort!(int) ( arr,   function int(int i1,int i2) { return i1 - i2; }    );
>
>It is simple and works *30% faster* than D builtin sort. Walter, please, pay 
>attention - C standard qsort is a piece of...

I could see having the generic array.sort use TypeInfo and its opCmp and have a
templated sort in Phobos for those cases when people want a sort that can be
optimized for their type (where the comparison function is specified some other
way than through the TypeInfo - either explicitly at the call site as you do
here or through opCmp operator lookup).

Keeping an API where users don't have to know about templates would be nice
since templates are an advanced maneuver.
March 09, 2005
Re: A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]
Matthew wrote:
<snip>
>>>What prevents the compiler from generating sorting based on arbitrary 
>>>difference (e.g. address of instance) for X, and using the 
>>>*non-polymorphic* Y::opCmp(Y) ?? (I know all methods are polymorphic 
>>>in D, but
>>
>> What would be the purpose of making address of instance the default 
>> sorting key?  Surely sorting an array of X would be a compiler error.
> 
> For AAs, not for arrays.
<snip>

This applies here as well:

http://www.digitalmars.com/d/garbage.html

"Depending on the ordering of pointers:

	if (p1 < p2)		// error: undefined behavior
	    ...
	
since, again, the garbage collector can move objects around in memory."

Logically, it would hook up an AA implementation that doesn't rely on an 
ordering.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home