Thread overview | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 05, 2004 Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Walter this is essencial. not only for streaming libraries, but simply in general.. an Tc = Ta + Tb doesn't have ANY preference for any of those 3 types. it should be Tc opAdd(Ta a,Tb b) {} and not Tc Ta.opAdd(Tb b) {} or Tc Tb.opAddR(Ta a) {} or even worse, both! just get rid of it. binary operators don't belong to a member. they never did. and if you release that essencial missconcept, and replace it by the only real one, we gain immediate access to a very fast implementable typesave, and extendable streaming library.. Tc operator add(Ta a,Tb b) { } would be my prefered way. |
January 05, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to davepermen | Me too, I find a little weird the syntax Ta.opAdd(Tb) but, if I remember, this is the standard way to overload operators in C++, too. Maybe, if cannot be simply dropped, an alternative definition will be suitable. In article <btbq8o$2g9e$1@digitaldaemon.com>, davepermen says... > >Walter > >this is essencial. not only for streaming libraries, but simply in general.. an > >Tc = Ta + Tb doesn't have ANY preference for any of those 3 types. it should be > >Tc opAdd(Ta a,Tb b) {} > >and not > >Tc Ta.opAdd(Tb b) {} > >or > >Tc Tb.opAddR(Ta a) {} > >or even worse, both! > >just get rid of it. binary operators don't belong to a member. they never did. > >and if you release that essencial missconcept, and replace it by the only real one, we gain immediate access to a very fast implementable typesave, and extendable streaming library.. > >Tc operator add(Ta a,Tb b) { } > >would be my prefered way. > > |
January 05, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Felix | In article <btbv9t$2p2s$1@digitaldaemon.com>, Felix wrote: > Me too, I find a little weird the syntax Ta.opAdd(Tb) but, if I remember, this is the standard way to overload operators in C++, too. Maybe, if cannot be simply dropped, an alternative definition will be suitable. There's no "standard" way in C++, you can pick any way you like. The things that affect your choice are the same with operators and other functions: - only member functions/operators can be overridden in a derived class - only non-member functions can be used to extend the class after it has been closed For example, suppose that the standard output mechanism in D would be something like Printer stdout; void main() { stdout ~ "Hello world " ~ 1 ~ 2 ~ 3 ~ endl; } And Printer implemented something like: class Printer { Printer opCat(int i) { .. } Printer opCat(char[] c) { .. } Printer opCat(Object o) { .. } } [replace Printer with OutputStream if you feel very generic] then the only way to introduce a new printable user-defined type, say Vector3, that isn't derived from Object but still can be printed to stdout is to make a free-standing function: Printer opCat(Printer p, Vector3 v) { p ~ "(" ~ v.x ~ ", " ~ v.y ~ ", " ~ v.z ~ ")"; } That is, if that was possible in D. You can do that in C++. If D was an OO only language, then making types not derived from Object would not be possible and the issue would be moot. Heck, we could be as well programming in Java. But I gather D is supposed be multiparadigm and all that, and you ought to be able to do stuff also without objects if you want. I object to objects. And if there is some template code somewhere, saying "stdout ~ t" where t is of type which is argument for the template, you sure as hell want your Vector3 to be printed instead of getting a message along the lines of "Printer does not have member function opCat(Printer, Vector3). Wanna change it? You can't! Bwahaha!". Duh! So to conclude the rant, I fully agree with davepermen: > just get rid of it. binary operators don't belong to a member. they never did. and Matthew: > That's something we need that is supported by a large number of issues, not just this one. It's an absolute must, and I can't seee Walter escaping us on this one. :) The only potential problems I see with free-standing operators are: 1. Importing or not importing a module containing operators will affect the way functions are overloaded. "a + b" might mean a different thing after adding an import. On the other hand, normal function calls are already vulnerable for this and I haven't experienced any problems whatsoever. Nor have I had any problems with the issue in C++, where it also exists. 2. The overloading rules might be a tad more complex with freestanding operators. That is, they might require some thinking so that they don't cause any surprises. Maybe there is someone less tired to perform the thinking ;) Complexity doesn't bother me if the rules are sufficiently simple to grasp intuitively. (Unless they end up in some Snake-Tongued Two-Phased Koenig Lookup or similar maze of mirrors) If there are any other valid reasons against non-member operators, please bring them forth because I for one have forgotten them. Did the original D "vision" include them? Why/why not? Is the reason that they haven't been implemented a reason of principle or merely a practical one? By tackling those issues one by one we might even arrive at a solution that satisfies everyone. At least, one can hope... -Antti |
January 05, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to davepermen | Hear, hear! "davepermen" <davepermen_member@pathlink.com> wrote in message news:btbq8o$2g9e$1@digitaldaemon.com... > Walter > > this is essencial. not only for streaming libraries, but simply in general.. an > > Tc = Ta + Tb doesn't have ANY preference for any of those 3 types. it should be > > Tc opAdd(Ta a,Tb b) {} > > and not > > Tc Ta.opAdd(Tb b) {} > > or > > Tc Tb.opAddR(Ta a) {} > > or even worse, both! > > just get rid of it. binary operators don't belong to a member. they never did. > > and if you release that essencial missconcept, and replace it by the only real > one, we gain immediate access to a very fast implementable typesave, and extendable streaming library.. > > Tc operator add(Ta a,Tb b) { } > > would be my prefered way. > > |
January 06, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Antti Sykäri | I agree it would probably be better to have binary overloading decoupled from methods (trading off run-time dispatching against extending classes without subclassing). But... from the D doc: "In D, function overloading is simple. It matches exactly, it matches with implicit conversions, or it does not match. If there is more than one match, it is an error." So does that mean I can't specialize an existing function like: Number opAdd(Number, int) {...} NumberSubclass opAdd(NumberSubclass,int) {...} If I have a variable of type NumberSubclass and I write "x+1" then it could match both (one exactly and the other with an implicit conversion) and so that would be an error. Or what if I had a subclass of NumberSubclass (so there would be two implicit conversion matches). It seems to me that this would make the proposed behavior of binary operator overloading less useful. Not unusable, I suppose. It would worth looking at a bunch of examples to see what would actually happen with either design and what the advantages and disadvantages of each would be. I for one can't immediately tell why one or the other would be a "no-brainer". -Ben "Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbvjcbm.69b.jsykari@pulu.hut.fi... > In article <btbv9t$2p2s$1@digitaldaemon.com>, Felix wrote: > > Me too, I find a little weird the syntax Ta.opAdd(Tb) but, if I remember, this > > is the standard way to overload operators in C++, too. Maybe, if cannot be > > simply dropped, an alternative definition will be suitable. > > There's no "standard" way in C++, you can pick any way you like. The things that affect your choice are the same with operators and other functions: > > - only member functions/operators can be overridden in a derived class > - only non-member functions can be used to extend the class after it has > been closed > > For example, suppose that the standard output mechanism in D would be something like > > Printer stdout; > void main() > { > stdout ~ "Hello world " ~ 1 ~ 2 ~ 3 ~ endl; > } > > And Printer implemented something like: > > class Printer > { > Printer opCat(int i) { .. } > Printer opCat(char[] c) { .. } > Printer opCat(Object o) { .. } > } > > [replace Printer with OutputStream if you feel very generic] > > then the only way to introduce a new printable user-defined type, say Vector3, that isn't derived from Object but still can be printed to stdout is to make a free-standing function: > > Printer opCat(Printer p, Vector3 v) > { > p ~ "(" ~ v.x ~ ", " ~ v.y ~ ", " ~ v.z ~ ")"; > } > > That is, if that was possible in D. You can do that in C++. If D was an OO only language, then making types not derived from Object would not be possible and the issue would be moot. Heck, we could be as well programming in Java. But I gather D is supposed be multiparadigm and all that, and you ought to be able to do stuff also without objects if you want. I object to objects. > > And if there is some template code somewhere, saying "stdout ~ t" where t is of type which is argument for the template, you sure as hell want your Vector3 to be printed instead of getting a message along the lines of "Printer does not have member function opCat(Printer, Vector3). Wanna change it? You can't! Bwahaha!". Duh! > > So to conclude the rant, I fully agree with davepermen: > > > just get rid of it. binary operators don't belong to a member. they never did. > > and Matthew: > > > That's something we need that is supported by a large number of issues, not just this one. It's an absolute must, and I can't seee Walter escaping us on this one. :) > > The only potential problems I see with free-standing operators are: > > 1. Importing or not importing a module containing operators will affect > the way functions are overloaded. "a + b" might mean a different > thing after adding an import. On the other hand, normal function > calls are already vulnerable for this and I haven't experienced any > problems whatsoever. Nor have I had any problems with the issue in > C++, where it also exists. > > 2. The overloading rules might be a tad more complex with freestanding > operators. That is, they might require some thinking so that they > don't cause any surprises. Maybe there is someone less tired to > perform the thinking ;) Complexity doesn't bother me if the rules are > sufficiently simple to grasp intuitively. (Unless they end up in some > Snake-Tongued Two-Phased Koenig Lookup or similar maze of mirrors) > > If there are any other valid reasons against non-member operators, please bring them forth because I for one have forgotten them. Did the original D "vision" include them? Why/why not? Is the reason that they haven't been implemented a reason of principle or merely a practical one? > > By tackling those issues one by one we might even arrive at a solution that satisfies everyone. At least, one can hope... > > -Antti > |
January 06, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | "Ben Hinkle" <bhinkle4@juno.com> wrote in message news:btd7ks$1li5$1@digitaldaemon.com... > I agree it would probably be better to have binary overloading decoupled > from methods (trading off run-time dispatching against extending classes > without subclassing). But... from the D doc: > "In D, function overloading is simple. It matches exactly, it matches with > implicit conversions, or it does not match. If there is more than one match, > it is an error." > > So does that mean I can't specialize an existing function like: > Number opAdd(Number, int) {...} > NumberSubclass opAdd(NumberSubclass,int) {...} > > If I have a variable of type NumberSubclass and I write "x+1" then it could > match both (one exactly and the other with an implicit conversion) and so > that would be an error. Or what if I had a subclass of NumberSubclass (so > there would be two implicit conversion matches). I sincerely hope that the compiler could umabiguously match the second operator. If not, we're storing up a heap of trouble for later. Walter, can you clarify what will happen here? > It seems to me that this would make the proposed behavior of binary operator > overloading less useful. Not unusable, I suppose. It would worth looking at > a bunch of examples to see what would actually happen with either design and > what the advantages and disadvantages of each would be. I for one can't immediately tell why one or the other would be a "no-brainer". > > -Ben > > "Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbvjcbm.69b.jsykari@pulu.hut.fi... > > In article <btbv9t$2p2s$1@digitaldaemon.com>, Felix wrote: > > > Me too, I find a little weird the syntax Ta.opAdd(Tb) but, if I > remember, this > > > is the standard way to overload operators in C++, too. Maybe, if cannot > be > > > simply dropped, an alternative definition will be suitable. > > > > There's no "standard" way in C++, you can pick any way you like. The things that affect your choice are the same with operators and other functions: > > > > - only member functions/operators can be overridden in a derived class > > - only non-member functions can be used to extend the class after it has > > been closed > > > > For example, suppose that the standard output mechanism in D would be something like > > > > Printer stdout; > > void main() > > { > > stdout ~ "Hello world " ~ 1 ~ 2 ~ 3 ~ endl; > > } > > > > And Printer implemented something like: > > > > class Printer > > { > > Printer opCat(int i) { .. } > > Printer opCat(char[] c) { .. } > > Printer opCat(Object o) { .. } > > } > > > > [replace Printer with OutputStream if you feel very generic] > > > > then the only way to introduce a new printable user-defined type, say Vector3, that isn't derived from Object but still can be printed to stdout is to make a free-standing function: > > > > Printer opCat(Printer p, Vector3 v) > > { > > p ~ "(" ~ v.x ~ ", " ~ v.y ~ ", " ~ v.z ~ ")"; > > } > > > > That is, if that was possible in D. You can do that in C++. If D was an OO only language, then making types not derived from Object would not be possible and the issue would be moot. Heck, we could be as well programming in Java. But I gather D is supposed be multiparadigm and all that, and you ought to be able to do stuff also without objects if you want. I object to objects. > > > > And if there is some template code somewhere, saying "stdout ~ t" where t is of type which is argument for the template, you sure as hell want your Vector3 to be printed instead of getting a message along the lines of "Printer does not have member function opCat(Printer, Vector3). Wanna change it? You can't! Bwahaha!". Duh! > > > > So to conclude the rant, I fully agree with davepermen: > > > > > just get rid of it. binary operators don't belong to a member. they never did. > > > > and Matthew: > > > > > That's something we need that is supported by a large number of issues, not just this one. It's an absolute must, and I can't seee Walter escaping us on this one. :) > > > > The only potential problems I see with free-standing operators are: > > > > 1. Importing or not importing a module containing operators will affect > > the way functions are overloaded. "a + b" might mean a different > > thing after adding an import. On the other hand, normal function > > calls are already vulnerable for this and I haven't experienced any > > problems whatsoever. Nor have I had any problems with the issue in > > C++, where it also exists. > > > > 2. The overloading rules might be a tad more complex with freestanding > > operators. That is, they might require some thinking so that they > > don't cause any surprises. Maybe there is someone less tired to > > perform the thinking ;) Complexity doesn't bother me if the rules are > > sufficiently simple to grasp intuitively. (Unless they end up in some > > Snake-Tongued Two-Phased Koenig Lookup or similar maze of mirrors) > > > > If there are any other valid reasons against non-member operators, please bring them forth because I for one have forgotten them. Did the original D "vision" include them? Why/why not? Is the reason that they haven't been implemented a reason of principle or merely a practical one? > > > > By tackling those issues one by one we might even arrive at a solution that satisfies everyone. At least, one can hope... > > > > -Antti > > > > |
January 06, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Antti Sykäri | "Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbvjcbm.69b.jsykari@pulu.hut.fi... > If there are any other valid reasons against non-member operators, please bring them forth because I for one have forgotten them. Did the original D "vision" include them? Why/why not? Is the reason that they haven't been implemented a reason of principle or merely a practical one? The problem is that if they were implemented, then there'd be a need for Koenig lookup. Once there's Koenig lookup, then there's the export lookup madness. |
January 06, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:btda5i$1puo$1@digitaldaemon.com... > > "Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbvjcbm.69b.jsykari@pulu.hut.fi... > > If there are any other valid reasons against non-member operators, please bring them forth because I for one have forgotten them. Did the original D "vision" include them? Why/why not? Is the reason that they haven't been implemented a reason of principle or merely a practical one? > > The problem is that if they were implemented, then there'd be a need for Koenig lookup. With you so far > Once there's Koenig lookup, then there's the export lookup madness. Please explain |
January 06, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | "Matthew" <matthew.hat@stlsoft.dot.org> wrote in message news:btdalv$1qml$1@digitaldaemon.com... > > "Walter" <walter@digitalmars.com> wrote in message news:btda5i$1puo$1@digitaldaemon.com... > > > > "Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbvjcbm.69b.jsykari@pulu.hut.fi... > > > If there are any other valid reasons against non-member operators, please bring them forth because I for one have forgotten them. Did the original D "vision" include them? Why/why not? Is the reason that they haven't been implemented a reason of principle or merely a practical one? > > > > The problem is that if they were implemented, then there'd be a need for Koenig lookup. > > With you so far > > > Once there's Koenig lookup, then there's the export lookup madness. > > Please explain I've done some extensive googling for info on export. It seems the main difficulty with export is the ADL. The two phase lookup comes in to play, once when the template is defined and the other when it is instantiated. The second lookup is the ADL one. The ADL can cut across all of the 'translation units', meaning an arbitrarilly large number of separate symbol tables need to be analyzed. This is essentially madness. As best as I can tell, this problem was not realized when export was voted into the Standard, and is the source of many opinions that export is unimplementable. EDG proved it could be implemented, reportedly consuming 3 man years, but I don't hear any more about the alleged advantages of export (code hiding, faster compilation), and hence I suspect those advantages do not occur in practice. Export is a canonical example of how backwards compatibility with seemingly innocuous design decisions can lead to disaster. I do not wish to import that madness into D <g>. |
January 06, 2004 Re: Free Operator Function Overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | "Matthew" <matthew.hat@stlsoft.dot.org> wrote in message news:btd95n$1o1a$1@digitaldaemon.com... > > "Ben Hinkle" <bhinkle4@juno.com> wrote in message news:btd7ks$1li5$1@digitaldaemon.com... > > I agree it would probably be better to have binary overloading decoupled > > from methods (trading off run-time dispatching against extending classes > > without subclassing). But... from the D doc: > > "In D, function overloading is simple. It matches exactly, it matches > with > > implicit conversions, or it does not match. If there is more than one > match, > > it is an error." > > > > So does that mean I can't specialize an existing function like: > > Number opAdd(Number, int) {...} > > NumberSubclass opAdd(NumberSubclass,int) {...} > > > > If I have a variable of type NumberSubclass and I write "x+1" then it > could > > match both (one exactly and the other with an implicit conversion) and so > > that would be an error. Or what if I had a subclass of NumberSubclass (so > > there would be two implicit conversion matches). > > I sincerely hope that the compiler could umabiguously match the second operator. If not, we're storing up a heap of trouble for later. > > Walter, can you clarify what will happen here? It'll match the second, since it is an exact match. The first is a match with conversions. |
Copyright © 1999-2021 by the D Language Foundation