Jump to page: 1 2
Thread overview
Round-up of the excuses for keeping Object.opCmp, and rebuttals to them
Sep 13, 2004
Stewart Gordon
Sep 13, 2004
Ivan Senji
Sep 13, 2004
Ben Hinkle
Sep 14, 2004
Stewart Gordon
A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]
Mar 09, 2005
Matthew
Mar 09, 2005
Andrew Fedoniouk
Mar 09, 2005
Ben Hinkle
A proposal for a new, improved sort (was: A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them])
Mar 09, 2005
Stewart Gordon
Mar 09, 2005
Andrew Fedoniouk
Mar 09, 2005
Ben Hinkle
Mar 10, 2005
Andrew Fedoniouk
Mar 09, 2005
Ben Hinkle
Mar 09, 2005
Stewart Gordon
Mar 09, 2005
Matthew
Mar 09, 2005
Stewart Gordon
September 13, 2004
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
"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
"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
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
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
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
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
"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
>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
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