Thread overview | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 22, 2002 Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Ok, so one more time about operator overloading... :) I read all the posts about operator overloading but I'm still a bit unsure about it...Do I want it, or don't I... I like about operator overloading the fact that you can add, subtract, compare or assign objects to one another much the same way as you can with normal primitive types. I hate some uses of operator overloading which seem really confusing to me. I always disliked the way cout and cin work. But maybe there is some middle ground? A compromise that could make everybody happy? Here is my idea: Think of Java, if you know it. It contains interfaces just like D. One of these interfaces is called Clonable. If you want your object to be copied to another, you implement Clonable. Now what if we could combine these kinds of interfaces with a form of predefined operator overloading. You would have a few predefined interfaces: IComparable, IAssignable, ISortable, IAddable, ISubtractable, IMultiplyable, IDividable...you get the idea. D would be able to check if an object implemented any of these interfaces and would automagically provide the suitable operators. I have already tried to implement something like this in C++ and I actually got IAssignable and IComparable to work, but when I tried to add more I got into trouble with multiple inheritance. Just a thought, but I think this might be a solution that would make everybody happy! P.S: There is another thread about templates which contains some sort of a variation on this: Constrained Genericity (template suggestion) -- Stijn OddesE_XYZ@hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail |
January 22, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to OddesE | That could be an easy way to deal with the syntax part of it. Sounds promising. I assume the operator would just map to a "normal" looking pure virtual function, such as Addable Add(Addable other), which could then be overridden. Unfortunately in D all functions are virtual, so the calling overhead will be large, but at least it would be possible to accomplish the goal of making a class work like a built-in type. Sean "OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:a2k8u8$fao$1@digitaldaemon.com... > Ok, so one more time about operator overloading... :) > > I read all the posts about operator overloading but I'm still a bit unsure about it...Do I want it, or don't I... > > I like about operator overloading the fact that you > can add, subtract, compare or assign objects to > one another much the same way as you can with > normal primitive types. > > I hate some uses of operator overloading which > seem really confusing to me. I always disliked > the way cout and cin work. > > But maybe there is some middle ground? > A compromise that could make everybody happy? > > Here is my idea: > > Think of Java, if you know it. It contains interfaces > just like D. One of these interfaces is called Clonable. > If you want your object to be copied to another, > you implement Clonable. Now what if we could > combine these kinds of interfaces with a form of > predefined operator overloading. You would have > a few predefined interfaces: > > IComparable, IAssignable, ISortable, IAddable, > ISubtractable, IMultiplyable, IDividable...you get > the idea. > > D would be able to check if an object implemented > any of these interfaces and would automagically > provide the suitable operators. > > I have already tried to implement something like > this in C++ and I actually got IAssignable and > IComparable to work, but when I tried to add > more I got into trouble with multiple inheritance. > > Just a thought, but I think this might be a solution > that would make everybody happy! > > > P.S: There is another thread about templates which > contains some sort of a variation on this: > Constrained Genericity (template suggestion) > > -- > Stijn > OddesE_XYZ@hotmail.com > http://OddesE.cjb.net > __________________________________________ > Remove _XYZ from my address when replying by mail > > > > |
January 22, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to OddesE | "OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:a2k8u8$fao$1@digitaldaemon.com... > But maybe there is some middle ground? > A compromise that could make everybody happy? Actually, there might be. > Think of Java, if you know it. It contains interfaces > just like D. One of these interfaces is called Clonable. > If you want your object to be copied to another, > you implement Clonable. Now what if we could > combine these kinds of interfaces with a form of > predefined operator overloading. You would have > a few predefined interfaces: > > IComparable, IAssignable, ISortable, IAddable, > ISubtractable, IMultiplyable, IDividable...you get > the idea. > > D would be able to check if an object implemented > any of these interfaces and would automagically > provide the suitable operators. This is actually close to the concept of a "class" in Haskell. Haskell is a very interesting language for anyone who's into programming languages. It's designed from the ground up to be a pure functional language, which usually makes the imperative programmer queasy, but it's actually a very usable and mature language at this point. So, let me show a bit what Haskell calls classes. I'll change the syntax so as to make it more D-like or C++-like: --- typeclass Eq(a) { bool operator ==(a, a); bool operator !=(a, a); // Minimal complete defintion: // (==) or (!=) // [JCAB] These are default definitions... bool operator ==(a x, a y) { return not(x != y); } bool operator !=(a x, a y) { return not(x == y); } } --- This defines the class of all types (a is a type parameter) that have equality comparison in them. Then, you can define your own types, like a 3D vector: --- class Vector3D { float x, y, z; } --- And then (separately) give the vector the equality class: --- typeclassinstance Eq(Vector3D) { bool operator ==(Vector3D v0, Vector3D v1) { return v0.x == v1.x && v0.y == v1.y && v0.z == v1.z; } // operator != gets implemented from the default. } --- Of course, the implementation of something like this in D would follow more what Stijn was saying. In Haskell, it is assumed that polymorphic functions (and operators) like those defined in a type class like that can have an extra "hidden" parameter called the dictionary (you can assume it's like an extra virtual function table pointer) for each type class used in the implementation of the function. Type classes in Haskell can require that the type reference also implement other type classes (they call it inheritance, which it is after a fashion). The standard set of Haskell classes is: class Bounded a class Enum a class Eq a class (Fractional a) => Floating a class (Num a) => Fractional a class Functor f class (Real a, Enum a) => Integral a class Monad m class (Eq a, Show a, Eval a) => Num a class (Eq a) => Ord a class Read a class (Num a, Ord a) => Real a class (RealFrac a, Floating a) => RealFloat a class (Real a, Fractional a) => RealFrac a class Show a where => means "is required for". BTW, Haskell allows the programmer to use any sequence of symbol characters as operators, like +++ or <=|=>. And define their precedence and associativity. Salutaciones, JCAB |
January 22, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "Sean L. Palmer" <spalmer@iname.com> wrote in message news:a2kevr$j2g$1@digitaldaemon.com... > That could be an easy way to deal with the syntax part of it. Sounds promising. I assume the operator would just map to a "normal" looking pure > virtual function, such as Addable Add(Addable other), which could then be > overridden. > > Unfortunately in D all functions are virtual, so the calling overhead will be large, but at least it would be possible to accomplish the goal of making > a class work like a built-in type. > > Sean It is an interesting idea. While D defines all functions to be virtual, a good optimizing compiler can de-virtualize (!) any functions which are not overridden by a derived class. This is one example where D simplifies programming and reduces errors. In my C++ work, I do this manually (then I add a derived class, forget to add "virtual", and have a subtle bug. Argh!). Since an optimizing D compiler will de-virtualize all calls it can, it can potentially have many *fewer* virtual calls than the equivalent C++ program. |
January 23, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> ha scritto nel messaggio news:a2km7g$o9f$1@digitaldaemon.com... > [...] > While D defines all functions to be virtual, a good optimizing compiler can > de-virtualize (!) any functions which are not overridden by a derived class. > This is one example where D simplifies programming and reduces errors. In my > C++ work, I do this manually (then I add a derived class, forget to add "virtual", and have a subtle bug. Argh!). Since an optimizing D compiler will de-virtualize all calls it can, it can potentially have many *fewer* virtual calls than the equivalent C++ program. Here Java has a point: a 'final' class cannot be derived, so the optimizing compiler can de-virtualize all functions it can. When you try to derive from this class the compiler signal an error, so you can remove the little 'final' word and recompile safely. Ciao |
January 24, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a2ls2g$1hvv$1@digitaldaemon.com... > Here Java has a point: a 'final' class cannot be derived, so the optimizing > compiler can > de-virtualize all functions it can. > When you try to derive from this class the compiler signal an error, so you > can remove > the little 'final' word and recompile safely. True, but to me that 'final' keyword is there to compensate for a weakness in the optimizer. It's unnecessary. |
January 24, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> ha scritto nel messaggio news:a2nt3r$2v4f$3@digitaldaemon.com... > > "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a2ls2g$1hvv$1@digitaldaemon.com... > > Here Java has a point: a 'final' class cannot be derived, so the > optimizing > > compiler can > > de-virtualize all functions it can. > > When you try to derive from this class the compiler signal an error, so > you > > can remove > > the little 'final' word and recompile safely. > > True, but to me that 'final' keyword is there to compensate for a weakness in the optimizer. It's unnecessary. Ok, but this little word can work like C "register" one: - You don't need an optimizer to do easy optimization. Consider that not every compiler has a (good) optimizer, especially alpha or beta compilers ;-) - A final class can be safely optimized even in debug releases, this will ease debugging. - The average optimizer is simpler to write. - A good optimizer can optimize even non-final classes (and even ignore final ones), as you stated, and as the 'register' keyword works in C. PS: I suppose there is no 'register' keyword in D, right? Ciao |
January 24, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "Sean L. Palmer" <spalmer@iname.com> wrote in message news:a2kevr$j2g$1@digitaldaemon.com... > That could be an easy way to deal with the syntax part of it. Sounds promising. I assume the operator would just map to a "normal" looking pure > virtual function, such as Addable Add(Addable other), which could then be > overridden. > > Unfortunately in D all functions are virtual, so the calling overhead will be large, but at least it would be possible to accomplish the goal of making > a class work like a built-in type. > > Sean That is indeed exactly what I was thinking of. In my opinions there are at least three benefits to using such an approach: 1. You have a standardized way of creating "operators". If you would implement IAssignable, the operator = would work for your class. If you implement IAddable, then operator + would also work. Combining the two would automatically give you operator += as well. Because the routines are standardized, and because D would make smart combinations of routines to give you combined operators such as +=, you would have to implement less functions to support more operators and errors would be made less frequently. 2. Everyone can choose. If the interface IAddable would contain a pure virtual method Add(), this would be standard. So people can choose wheter to use Add() or +, knowing they will always be both fully supported and work exactly the same, or both of them won't be supported at all. Hell, using DML you could even allow both forms to be exchanged into one another depending on a preferences setting. 3. You can detect wheter a class supports a certain type of operator. Using RTTI you can determine if a class IS A IAddable or not. This might be *very* valuable. This could also be used to force a class to support an operator. How about: COrderedList.Insert (ISortable element) ? I also see some problems for this approach though: 1. Speed. It might be too slow to implement operator overloading this way. But I really don't know how good or bad a compiler might optimise this. I imagine it would be possible for the compiler to change obj + obj to obj.Add (obj) at compile time, but I don't know if this is in fact possible. 2. Operator 'dependencies'... Think of ISortable, it would probably have a method IsLess () or something, but it doesn't really make sense to implement that without implementing IComparable's IsEqual(). Now this problem isn't new, it is just an old problem that isn't solved. In C++ it is also possible to overload < but not ==. You could try to make ISortable inherit from IComparable, so implementing IsLess forces you to implement IsEqual too. I tried this in my C++ experiment but ran into trouble with virtual inheritance. I think that it should be possible using interfaces though... To give you more of a feeling of how it would work, I'll post some sample code. I'm typing this in my newsreader, so please forgive me my 'spelling'. :) interface IAssignable { void Assign (Object obj); void Assign (int i); void Assign (bool b); void Assign (double d); void Assign (char c); // ... It gets dull, but you get the idea // One Assign for Object's and one for // each standard type. } interface IAddable { void Add (Object obj); // ... } interface ISubtractable { void Subtract (Object obj); // ... } interface IDividable { void Divide (Object obj); // ... } interface IMutiplyable { void Multiply (Object obj); // ... } interface IComparable { bool IsEqual (Object obj); // ... } interface ISortable: IComparable { bool IsLess (Object obj); // ... } class CMyObject: IComparable { public int m_i; this (int i) {m_i = i}; bool IsEqual (Object obj) { CMyObject myObj = cast (CMyObject) obj; if (myObj == null) return false; return (this.m_i == myObj.m_i); } bool IsLess (Object obj) { CMyObject myObj = cast (CMyObject) obj; if (myObj == null) return false; return (this.m_i < myObj.m_i); } } // And how you would use it: CMyObject obj1 = new CMyObject (10); CMyObject obj2 = new CMyObject (13); if (obj1 < obj2) // Would call: // if (obj1.Less (obj2)) if (obj1 <= obj2) // Would call: // if ((obj1.Less (obj2)) || (obj1.IsEqual (obj2))) if (obj1 > obj2) // Would call: // if ((! obj1.Less (obj2)) && (! obj1.IsEqual (obj2))) if (obj1 >= obj2) // Would call: // if ((! obj1.Less (obj2))) Well that's about it. Greets! -- Stijn OddesE_XYZ@hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail |
January 25, 2002 Re: Operator overloading: A way to make everybody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a2p5j5$qlp$1@digitaldaemon.com... > Ok, but this little word can work like C "register" one: > - You don't need an optimizer to do easy optimization. Consider that not > every compiler > has a (good) optimizer, especially alpha or beta compilers ;-) It isn't that hard to do the final optimization. You just look to see if there are any derived classes, and if any of those derived classes override it. > - A final class can be safely optimized even in debug releases, this will > ease debugging. > - The average optimizer is simpler to write. True, but I propose to simplify the language, and am willing to put a little more burden on the compiler to get that. You can remind me that I propose that D be easy to write a compiler for, and I respond that it isn't necessary for a compiler to implement this optimization! > - A good optimizer can optimize even non-final classes (and even ignore > final ones), as you stated, > and as the 'register' keyword works in C. > > PS: I suppose there is no 'register' keyword in D, right? Correct. C compilers haven't been dependent on it for over a decade. |
January 25, 2002 Re: Operator overloading: A way to make somebody happy? | ||||
---|---|---|---|---|
| ||||
Posted in reply to OddesE | This form could be a very good way of solving the problem for classes. But what the main purpose of operator overloading ? For me is defining new operations over simple types. The are not strong meaning doing : computer a, b, c; a = new computer(1,2); a = new computer(1,7); c = a + b; For example candidates could be Date and Time, Grades , Minutes, Seconds Celsius <-> Fahrenheit Meters <-> Foots Kilo, Pounds, etc... Matematic types like complex ( already added ) and so on Geometric types Matrix types , and etc How could this be done with interfaces. "OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:a2k8u8$fao$1@digitaldaemon.com... Ok, so one more time about operator overloading... :) I read all the posts about operator overloading but I'm still a bit unsure about it...Do I want it, or don't I... I like about operator overloading the fact that you can add, subtract, compare or assign objects to one another much the same way as you can with normal primitive types. I hate some uses of operator overloading which seem really confusing to me. I always disliked the way cout and cin work. But maybe there is some middle ground? A compromise that could make everybody happy? Here is my idea: Think of Java, if you know it. It contains interfaces just like D. One of these interfaces is called Clonable. If you want your object to be copied to another, you implement Clonable. Now what if we could combine these kinds of interfaces with a form of predefined operator overloading. You would have a few predefined interfaces: IComparable, IAssignable, ISortable, IAddable, ISubtractable, IMultiplyable, IDividable...you get the idea. D would be able to check if an object implemented any of these interfaces and would automagically provide the suitable operators. I have already tried to implement something like this in C++ and I actually got IAssignable and IComparable to work, but when I tried to add more I got into trouble with multiple inheritance. Just a thought, but I think this might be a solution that would make everybody happy! P.S: There is another thread about templates which contains some sort of a variation on this: Constrained Genericity (template suggestion) -- Stijn OddesE_XYZ@hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail |
Copyright © 1999-2021 by the D Language Foundation