digitalmars.D - Comparing apples and oranges
- Andrei Alexandrescu (25/25) Sep 29 2009 Consider:
- Jeremie Pelletier (4/41) Sep 29 2009 You can already explicitly do "(new Apple).opEquals(new Orange);" so why...
- Ary Borenszweig (2/15) Sep 29 2009 Has this brought problems to anyone ever?
- Andrei Alexandrescu (5/21) Sep 29 2009 I'm not sure about this particular aspect, but in Java the related
- Denis Koroskin (11/36) Sep 29 2009 I believe Java and C# took bool Object.equals(Object other); way because...
- bearophile (4/8) Sep 29 2009 I think that asks for some extra optimizations that I think currently D ...
- Jarrett Billingsley (8/16) Sep 29 2009 I agree, opEquals and opCmp in Object feel like out-of-date relics.
- Stewart Gordon (20/34) Sep 29 2009 I believe Java still does internally, and generics are just a coding
- Andrei Alexandrescu (6/59) Sep 29 2009 What would you replace it with?
- Yigal Chripun (2/62) Sep 29 2009 How about implementing multiple-dispatch than?
- Andrei Alexandrescu (3/71) Sep 29 2009 Yah, how about it? :o)
Consider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible? The comparison would still remain possible by casting to a parent class: writeln(cast(Object) new Apple == cast(Object) new Orange); I could think of rare cases in which one would want two sibling types to compare equal. Consider: class Matrix { ... } // No state added, operations optimized with BLAS class BLASMatrix : Matrix {} // No state added, operations optimized with LAPACK class LAPACKMatrix : Matrix {} Since neither derived class adds any state, both act in comparisons just like the base class Matrix, so it's valid to compare a BLASMatrix with a LAPACKMatrix. How do you think we should go about this? Stay error-prone for the benefit of a few cases, or disallow sibling class comparisons statically? Andrei
Sep 29 2009
Andrei Alexandrescu wrote:Consider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible? The comparison would still remain possible by casting to a parent class: writeln(cast(Object) new Apple == cast(Object) new Orange); I could think of rare cases in which one would want two sibling types to compare equal. Consider: class Matrix { ... } // No state added, operations optimized with BLAS class BLASMatrix : Matrix {} // No state added, operations optimized with LAPACK class LAPACKMatrix : Matrix {} Since neither derived class adds any state, both act in comparisons just like the base class Matrix, so it's valid to compare a BLASMatrix with a LAPACKMatrix. How do you think we should go about this? Stay error-prone for the benefit of a few cases, or disallow sibling class comparisons statically? AndreiYou can already explicitly do "(new Apple).opEquals(new Orange);" so why not first resolve == to opEquals and then try to match the parameters, walking through all known opEquals until a matching one is found.
Sep 29 2009
Andrei Alexandrescu wrote:Consider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible?Has this brought problems to anyone ever?
Sep 29 2009
Ary Borenszweig wrote:Andrei Alexandrescu wrote:I'm not sure about this particular aspect, but in Java the related method equals() has been a perennial source of issues. Just google for java equals. AndreiConsider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible?Has this brought problems to anyone ever?
Sep 29 2009
On Tue, 29 Sep 2009 18:54:28 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Consider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible? The comparison would still remain possible by casting to a parent class: writeln(cast(Object) new Apple == cast(Object) new Orange); I could think of rare cases in which one would want two sibling types to compare equal. Consider: class Matrix { ... } // No state added, operations optimized with BLAS class BLASMatrix : Matrix {} // No state added, operations optimized with LAPACK class LAPACKMatrix : Matrix {} Since neither derived class adds any state, both act in comparisons just like the base class Matrix, so it's valid to compare a BLASMatrix with a LAPACKMatrix. How do you think we should go about this? Stay error-prone for the benefit of a few cases, or disallow sibling class comparisons statically? Andreithey lacked generics intially and stored all the instances as Objects in containers (having equals method in Object allowed them proper ordering etc). D doesn't suffer from that problem and doesn't have to follow the same way those languages took. BTW, nowadays, they define IComparable<T> interface, which is a recommended way to implement comparison functions. That's why I'm all for removing opEquals from Object.
Sep 29 2009
Denis Koroskin:BTW, nowadays, they define IComparable<T> interface, which is a recommended way to implement comparison functions. That's why I'm all for removing opEquals from Object.I think that asks for some extra optimizations that I think currently D front-end doesn't perform. Bye, bearophile
Sep 29 2009
On Tue, Sep 29, 2009 at 11:17 AM, Denis Koroskin <2korden gmail.com> wrote:they lacked generics intially and stored all the instances as Objects in containers (having equals method in Object allowed them proper ordering etc). D doesn't suffer from that problem and doesn't have to follow the same way those languages took.I agree, opEquals and opCmp in Object feel like out-of-date relics. It's particularly annoying how, if you want your classes to behave with arrays/AAs, you must override opEquals(Object), meaning you have to do silly downcasts at runtime.BTW, nowadays, they define IComparable<T> interface, which is a recommended way to implement comparison functions.I think D, with its much better generic support, could basically use duck typing and achieve the same effects without the penalty of an interface.
Sep 29 2009
Jarrett Billingsley wrote:On Tue, Sep 29, 2009 at 11:17 AM, Denis Koroskin <2korden gmail.com> wrote:I believe Java still does internally, and generics are just a coding convenience. http://en.wikipedia.org/wiki/Generics_in_Java#Type_erasurethey lacked generics intially and stored all the instances as Objects in containers (having equals method in Object allowed them proper ordering etc).I've always been against opCmp being in Object. opEquals being in Object is harder to dismiss, as I can imagine that someone might find a use case for being able to store an arbitrary mix of objects in a container and in doing so be able to compare them. But I do wonder if Object.opEquals could work better. Maybe make it so that, if a class C contains a method opEquals(C), and opEquals(Object) has not been explicitly overridden by the programmer anywhere up the hierarchy, then opEquals(Object) will be automagically overridden to call opEquals(C). The only trouble is that I'm not sure how well this would work when interfaces are involved.D doesn't suffer from that problem and doesn't have to follow the same way those languages took.I agree, opEquals and opCmp in Object feel like out-of-date relics. It's particularly annoying how, if you want your classes to behave with arrays/AAs, you must override opEquals(Object), meaning you have to do silly downcasts at runtime.<snip> Both Java's Comparable and, AFAICMO, .NET's IComparable, are for ordering comparisons. Equality comparison is built into Object in both cases. Stewart.BTW, nowadays, they define IComparable<T> interface, which is a recommended way to implement comparison functions.
Sep 29 2009
Denis Koroskin wrote:On Tue, 29 Sep 2009 18:54:28 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:What would you replace it with? Note that IComparable<T> does not quite solve a lot of the problems, at least does not make things much easier for the programmer. Comparing objects is really a double dispatch problem. AndreiConsider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible? The comparison would still remain possible by casting to a parent class: writeln(cast(Object) new Apple == cast(Object) new Orange); I could think of rare cases in which one would want two sibling types to compare equal. Consider: class Matrix { ... } // No state added, operations optimized with BLAS class BLASMatrix : Matrix {} // No state added, operations optimized with LAPACK class LAPACKMatrix : Matrix {} Since neither derived class adds any state, both act in comparisons just like the base class Matrix, so it's valid to compare a BLASMatrix with a LAPACKMatrix. How do you think we should go about this? Stay error-prone for the benefit of a few cases, or disallow sibling class comparisons statically? Andreithey lacked generics intially and stored all the instances as Objects in containers (having equals method in Object allowed them proper ordering etc). D doesn't suffer from that problem and doesn't have to follow the same way those languages took. BTW, nowadays, they define IComparable<T> interface, which is a recommended way to implement comparison functions. That's why I'm all for removing opEquals from Object.
Sep 29 2009
On 29/09/2009 18:13, Andrei Alexandrescu wrote:Denis Koroskin wrote:How about implementing multiple-dispatch than?On Tue, 29 Sep 2009 18:54:28 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:What would you replace it with? Note that IComparable<T> does not quite solve a lot of the problems, at least does not make things much easier for the programmer. Comparing objects is really a double dispatch problem. AndreiConsider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible? The comparison would still remain possible by casting to a parent class: writeln(cast(Object) new Apple == cast(Object) new Orange); I could think of rare cases in which one would want two sibling types to compare equal. Consider: class Matrix { ... } // No state added, operations optimized with BLAS class BLASMatrix : Matrix {} // No state added, operations optimized with LAPACK class LAPACKMatrix : Matrix {} Since neither derived class adds any state, both act in comparisons just like the base class Matrix, so it's valid to compare a BLASMatrix with a LAPACKMatrix. How do you think we should go about this? Stay error-prone for the benefit of a few cases, or disallow sibling class comparisons statically? Andreibecause they lacked generics intially and stored all the instances as Objects in containers (having equals method in Object allowed them proper ordering etc). D doesn't suffer from that problem and doesn't have to follow the same way those languages took. BTW, nowadays, they define IComparable<T> interface, which is a recommended way to implement comparison functions. That's why I'm all for removing opEquals from Object.
Sep 29 2009
Yigal Chripun wrote:On 29/09/2009 18:13, Andrei Alexandrescu wrote:Yah, how about it? :o) AndreiDenis Koroskin wrote:How about implementing multiple-dispatch than?On Tue, 29 Sep 2009 18:54:28 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:What would you replace it with? Note that IComparable<T> does not quite solve a lot of the problems, at least does not make things much easier for the programmer. Comparing objects is really a double dispatch problem. AndreiConsider: class Apple {} class Orange {} void main() { writeln(new Apple == new Orange); } This program always prints "false". By and large, it is odd that one would attempt comparison between unrelated classes. I was thinking, is this ever legitimate, or we should just disallow it statically whenever possible? The comparison would still remain possible by casting to a parent class: writeln(cast(Object) new Apple == cast(Object) new Orange); I could think of rare cases in which one would want two sibling types to compare equal. Consider: class Matrix { ... } // No state added, operations optimized with BLAS class BLASMatrix : Matrix {} // No state added, operations optimized with LAPACK class LAPACKMatrix : Matrix {} Since neither derived class adds any state, both act in comparisons just like the base class Matrix, so it's valid to compare a BLASMatrix with a LAPACKMatrix. How do you think we should go about this? Stay error-prone for the benefit of a few cases, or disallow sibling class comparisons statically? Andreibecause they lacked generics intially and stored all the instances as Objects in containers (having equals method in Object allowed them proper ordering etc). D doesn't suffer from that problem and doesn't have to follow the same way those languages took. BTW, nowadays, they define IComparable<T> interface, which is a recommended way to implement comparison functions. That's why I'm all for removing opEquals from Object.
Sep 29 2009