D - Operator overloading.
- John Fletcher (15/15) Aug 14 2001 Quote from the specification for D:
- Walter (7/22) Aug 14 2001 I agree that operator overloading can be used for matrix and vector clas...
- John Fletcher (19/25) Aug 15 2001 A quaternion is an object which has four components. One is real. The ...
- Walter (15/43) Aug 15 2001 Wow! I see what you're doing now.
- John Fletcher (3/4) Aug 16 2001 It was a related program which had the bug you found for me a little whi...
- Rolf Campbell (16/45) Aug 16 2001 Whether it is easy to write good overloaded operators or not doesn't rem...
- Jonathan Cano (9/13) Aug 16 2001 Just because something is difficult is no reason to exclude it from the
- Carlo E. Prelz (16/21) Aug 17 2001 I think the problem here is to be able to balance the complexity you are
- Charles Hixson (17/28) Aug 17 2001 Overloaded operators can be quite useful, but perhaps the standard
- Walter (3/19) Aug 17 2001 Now this idea has a lot of merit! Thanks for posting it. I *like* it bei...
- Russell Bornschlegel (21/37) Aug 17 2001 Again, I think I read in Stroustrup the suggestion that a language
- Walter (5/13) Aug 17 2001 I admit that implementing iostream and just the way it *looks* turned me
- Sean L. Palmer (31/44) Oct 29 2001 If that were the case, STL iterators would be much harder to use... as
- Walter (5/9) Oct 30 2001 overloading,
- John English (20/23) May 02 2002 I don't see that resolving an overloaded operator is any easier just
- Roland (9/25) Aug 23 2001 Yes overloaded operators are useful.
- John English (16/21) May 02 2002 There are lots of other common applications, too; consider a Date
- Walter (9/18) May 06 2002 I don't know why Java decided to do dates that way, but I don't think it...
- Pavel Minayev (5/6) May 06 2002 I guess it's because you can then make properties like month, day, dayOf...
- OddesE (16/22) May 06 2002 it's
- John English (9/25) May 08 2002 So you can multiply and divide dates? Hmm... I wonder what 8 May 2002
- Russ Lewis (12/14) May 08 2002 You can't really multiply or divide a date...but you can do so for a tim...
- Roberto Mariottini (7/9) May 09 2002 It's the wrong question. The good is:
- OddesE (11/21) May 09 2002 What is the square root of -4?
- Russ Lewis (8/9) May 09 2002 It's 2j.
- Brendan McCane (12/18) Aug 16 2001 Gotta agree wholeheartedly with this. If you are doing any numerical
- Robert W. Cunningham (62/74) Aug 16 2001 Remember, from a distant perspective *all* "operators" are "syntactic su...
- Anthony Steele (7/10) Sep 09 2001 My 2c:
- Charles Hixson (41/61) Sep 10 2001 a) It's not a big feature if you already have overloaded
- Axel Kittenberger (8/10) Sep 10 2001 Well = will also be most like an overload assignment operator so:
- Charles Hixson (1/18) Sep 10 2001
- Charles Hixson (67/84) Sep 10 2001 Sorry about the empty reply.
- Axel Kittenberger (30/80) Sep 10 2001 Well fundamentally different was a false, it's even worse than that: it'...
- Charles Hixson (25/52) Sep 10 2001 A hashmap doesn't imply an ordering. I suppose that you can
- Axel Kittenberger (3/7) Sep 10 2001 No didn't mean sorting, but you've also two ways to access a hashmap, a)...
- timeless (2/4) Feb 04 2002 transitive
- a (11/17) Sep 10 2001 Just for arguments sake, if you had distinct user defined operators,
- Charles Hixson (5/19) Sep 11 2001 One could certainly define:
- a (6/29) Sep 11 2001 And we go from looking at (left == right) and not know if we have built
- Charles Hixson (7/23) Sep 12 2001 The built-in operators are still available. So that hasn't been
- kaffiene (27/31) Aug 17 2001 Operator overloading as it exists in C++ is unsatisfactory. Unless it c...
- John Fletcher (7/13) Aug 17 2001 I know of a C++ compiler (SALFORD C++
- John English (8/25) May 03 2002 Algol 68 did this too, many years ago.
- Christophe de Dinechin (61/93) Aug 17 2001 For LX, I invented the "written" notation. In D-like syntax, it would be...
- kaffiene (95/183) Aug 18 2001 That's really nice.
- Russell Bornschlegel (17/38) Aug 18 2001 As a counterpoint to this, I'll just point out that no one is forced
- kaffiene (29/62) Aug 18 2001 result - it
- Christophe de Dinechin (16/23) Aug 20 2001 The gain is scant (if not negative) for something like "cout <<". But it...
- Sheldon Simms (9/39) Aug 20 2001 I'm pretty sure that by "arbitrary precedence", he didn't mean that
- kaffiene (30/52) Aug 20 2001 user
- Charles Hixson (9/16) Aug 21 2001 It seems reasonable to me that all new operators should same precedence
- kaffiene (7/23) Aug 21 2001 well.
- Charles Hixson (5/39) Aug 22 2001 But you ignore the adjective "excessive". It makes a big difference
- Christophe de Dinechin (35/66) Aug 22 2001 I said it was an impression, I never claimed it was a fact. You did not ...
- kaffiene (38/66) Aug 22 2001 introducing
- kaffiene (16/88) Aug 22 2001 If everyone is dead keen on operator overloading, then let's have it. B...
- Russell Bornschlegel (5/12) Aug 22 2001 Agreed, with support for operators written with arbitrary Unicode.
- kaffiene (6/15) Aug 22 2001 new
- Eric Gerlach (84/112) Aug 26 2001 Hmph, it's really hard to decide where exactly to put a post when you're...
- Walter (5/117) Aug 26 2001 Thanks for the entertaining and excellent summary. BTW, what is
- Eric Gerlach (128/130) Aug 27 2001 It sounds like you are entreating me to treat you with another treatise....
- Walter (4/134) Aug 29 2001 Ok, I see. Thanks for the explanation. I'm not sure I'm ready to try it ...
- Russell Bornschlegel (22/33) Aug 26 2001 This is going to look like I'm jumping the fence repeatedly on
- Eric Gerlach (13/17) Aug 27 2001 I'm not too picky about operator overload being in or not (I was just
- Russell Borogove (6/10) Sep 05 2001 But as I point out, that arbitrary restriction doesn't make it
- Charles Hixson (4/18) Sep 06 2001 You can also confuse people by naming a routine that takes the
- Charles Hixson (6/29) Aug 27 2001 I prefer symbols that are easier to type on a standard keyboard, but I
- Eric Gerlach (3/4) Aug 27 2001 Yes, that was the downside to the whole idea... not many people have
- Angus Graham (30/31) Aug 22 2001 Not everyone is dead keen on it. I haven't commented on the subject (or
- Kent Sandvik (4/4) Aug 22 2001 Same here, I don't like operator overloads, the complexity added for
- kaffiene (10/40) Aug 22 2001 hehe - I don't like operator overloading either, but given that everyone...
- Arjan Knepper (6/20) Aug 23 2001 I Agree. Using (member) functions with a clear self explaining name as A...
- Walter (4/35) Aug 23 2001 and
- Dan Hursh (19/119) Aug 23 2001 It seemed like you were mostly against A + B and Add(A, B) being
- Charles Hixson (7/16) Aug 24 2001 But you can certainly do it the way you are talking about. Add (A, B)
- Sean L. Palmer (15/22) Oct 29 2001 I think it's funny that you believe that somebody that "is unfamiliar wi...
- Walter (10/32) Nov 02 2001 While operator overloading is an idea with many merits, I just don't see
- Robert W. Cunningham (20/23) Nov 03 2001 Much of the operator overloading I've seen often appears to be little mo...
- Roland (6/29) Nov 05 2001 I agree.
- Axel Kittenberger (14/17) Nov 05 2001 The problem arises what is if you have:
- Juarez Rudsatz (33/52) Nov 05 2001 This problem could not be soulved by defining operator precedence levels...
- Sean L. Palmer (25/84) Nov 05 2001 I think I'd rather deal with precedence in terms of existing operators i...
- Charles Hixson (4/4) Aug 17 2001 If the C++ overloading doesn't work well, then look at other languages.
- kaffiene (4/8) Aug 18 2001 Eiffel seems to do a lot of things well that C++ doesn't. But I'm a big...
- Charles Hixson (14/18) Aug 21 2001 Eiffel is much less flexible in many ways than C++. This is both good
- kaffiene (6/15) Aug 21 2001 bigot -
- John English (14/17) May 03 2002 Without overloading, one group does vec.plus(v2), another does
- OddesE (64/75) May 05 2002 of
- Tim Sweeney (26/41) Aug 17 2001 As someone who writes tons of vector math code in production application...
- a (10/32) Aug 18 2001 I'll second this. I understand that C++ overloads are insuficant but
- Christophe de Dinechin (3/6) Aug 20 2001 Why? Could you give an example?
- Dan Hursh (38/48) Aug 21 2001 It's hard to give an example without a concrete syntax to start with.
Quote from the specification for D: Operator overloading. The only practical applications for operator overloading seem to be implementing a complex floating point type, a string class, and smart pointers. D provides the first two natively, smart pointers are irrelevant in a garbage collected language. Another quote: D has many features to directly support features needed by numerics programmers, like direct support for the complex data type and defined behavior for NaN's and infinities. Comment: For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable. John Fletcher
Aug 14 2001
I agree that operator overloading can be used for matrix and vector classes, in fact, the first user of my C++ compiler used it to develop a matrix class! The results were disappointing, though. It's amazingly difficult to write a good class that overloads operators. What's a quaternion? 4 reals? -Walter John Fletcher wrote in message <3B78E154.BC62E006 aston.ac.uk>...Quote from the specification for D: Operator overloading. The only practical applications for operator overloading seem to be implementing a complex floating point type, a string class, and smart pointers. D provides the first two natively, smart pointers are irrelevant in a garbage collected language. Another quote: D has many features to directly support features needed by numerics programmers, like direct support for the complex data type and defined behavior for NaN's and infinities. Comment: For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable. John Fletcher
Aug 14 2001
Walter wrote:I agree that operator overloading can be used for matrix and vector classes, in fact, the first user of my C++ compiler used it to develop a matrix class! The results were disappointing, though. It's amazingly difficult to write a good class that overloads operators. What's a quaternion? 4 reals? -WalterA quaternion is an object which has four components. One is real. The other three can be viewed as three mutually perpendicular imaginary numbers. They were invented by Hamilton in the 1850's or thereabouts (before vectors) and now have a lot of use calculating rotations in three dimensions. See for example "SymbolicC++, An introduction to Computer Algebra using object oriented programming" T.K. Shi & W.H.Steeb http://issc.rau.ac.za/symbolic/symbolic.html who define a quaternion class. I use this software with DM compiler, making extensive use of templates and operator overloading, so that the top level program resembles as far as possible the algebra which is written down. You can see some the results of this in http://www.ceac.aston.ac.uk/clifford/paper25/index.htm It is difficult to write operator overloading classes well. I have used as a basis the work of Coplien. Some of the issues are around the creation of temporary copies along the way. I quite frequently have to extend the stack space to large values to get the programs to run. That is the attraction of a language with garbage collection. John Fletcher
Aug 15 2001
Wow! I see what you're doing now. "John Fletcher" <J.P.Fletcher aston.ac.uk> wrote in message news:3B7A3FCB.DD2550E7 aston.ac.uk...Walter wrote:classes,I agree that operator overloading can be used for matrix and vectortoin fact, the first user of my C++ compiler used it to develop a matrix class! The results were disappointing, though. It's amazingly difficultotherwrite a good class that overloads operators. What's a quaternion? 4 reals? -WalterA quaternion is an object which has four components. One is real. Thethree can be viewed as three mutually perpendicular imaginary numbers.Theywere invented by Hamilton in the 1850's or thereabouts (before vectors)and nowhave a lot of use calculating rotations in three dimensions. See for example "SymbolicC++, An introduction to Computer Algebra usingobjectoriented programming" T.K. Shi & W.H.Steeb http://issc.rau.ac.za/symbolic/symbolic.html who define a quaternion class. I use this software with DM compiler, making extensive use of templatesandoperator overloading, so that the top level program resembles as far aspossiblethe algebra which is written down. You can see some the results of thisinhttp://www.ceac.aston.ac.uk/clifford/paper25/index.htm It is difficult to write operator overloading classes well. I have used asabasis the work of Coplien. Some of the issues are around the creation of temporary copies along the way. I quite frequently have to extend thestackspace to large values to get the programs to run. That is the attractionof alanguage with garbage collection. John Fletcher
Aug 15 2001
Walter wrote:Wow! I see what you're doing now.It was a related program which had the bug you found for me a little while ago. John
Aug 16 2001
Whether it is easy to write good overloaded operators or not doesn't remove the handiness of their existance. How do you suggest matrix algebra be done in D? Matrix a = matrixMult(matrixAdd(c, d), e); or Matrix a = c.add(d).mult(e); ??? Neither one of these is especially usefull for complex expresssions. Also, another use for operator overloading is arbitrary presision Integers/Floats. If I want a 128-bit or a 256-bit integer, I want to be able to use it in normal mathematical expressions. -Rolf Campbell "Walter" <walter digitalmars.com> wrote in message news:9lbhub$20ib$1 digitaldaemon.com...I agree that operator overloading can be used for matrix and vectorclasses,in fact, the first user of my C++ compiler used it to develop a matrix class! The results were disappointing, though. It's amazingly difficult to write a good class that overloads operators. What's a quaternion? 4 reals? -Walter John Fletcher wrote in message <3B78E154.BC62E006 aston.ac.uk>...Quote from the specification for D: Operator overloading. The only practical applications for operator overloading seem to be implementing a complex floating point type, a string class, and smart pointers. D provides the first two natively, smart pointers are irrelevant in a garbage collected language. Another quote: D has many features to directly support features needed by numerics programmers, like direct support for the complex data type and defined behavior for NaN's and infinities. Comment: For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable. John Fletcher
Aug 16 2001
Walter wrote:I agree that operator overloading can be used for matrix and vector classes, in fact, the first user of my C++ compiler used it to develop a matrix class! The results were disappointing, though. It's amazingly difficult to write a good class that overloads operators.Just because something is difficult is no reason to exclude it from the language. If we never allowed folks to attempt things that are difficult we'd never make any progress. Operator overloading should definitely be in the language! -- Jonathan Cano Member of Technical Staff MMC Networks, Inc.
Aug 16 2001
Jonathan Cano wrote:Just because something is difficult is no reason to exclude it from the language. If we never allowed folks to attempt things that are difficult we'd never make any progress. Operator overloading should definitely be in the language!I think the problem here is to be able to balance the complexity you are inserting with the amount of real-life problems you are solving. Operator overloading implementation as a problem has been solved many times already. I personally agree with Walter's decision: operators mean something very precise for me. For me, adding fancy meanings to them would just add to the confusion of the result. Carlo -- * Se la Strada e la sua Virtu' non fossero state messe da parte, * K * Carlo E. Prelz - fluido fluido.as che bisogno ci sarebbe * di parlare tanto di amore e di rettitudine? (Chuang-Tzu)
Aug 17 2001
Carlo E. Prelz wrote:Jonathan Cano wrote: ...Overloaded operators can be quite useful, but perhaps the standard operators shouldn't be overloadable. Perhaps one should instead be able to define infix functions (i.e., operators) have a form like, O, just as colons, no control characters, no parens, bracketts, or braces, no backslash, and surrounded by colons. Also require white-space separation from everything else. So one could define :+: to add matrices, etc., and as these would really be functions, they should follow the normal overloading rules of functions. This would allow them to be easily parsed, would distinguish them clearly from the standard operators, and would provide the majority of the notational compactness that normal operators provide. The fact that A :+: B would be syntactic sugar for A.add (B) is minor, but convenient. As to precedence ... they should probably bind more strongly than any other operator, and all to the same degree. If you want to get fancy, you'ld need to use parentheses.I think the problem here is to be able to balance the complexity you are inserting with the amount of real-life problems you are solving. Operator overloading implementation as a problem has been solved many times already. I personally agree with Walter's decision: operators mean something very precise for me. For me, adding fancy meanings to them would just add to the confusion of the result. Carlo
Aug 17 2001
Charles Hixson wrote in message <3B7D2C6B.4040702 earthlink.net>...Overloaded operators can be quite useful, but perhaps the standard operators shouldn't be overloadable. Perhaps one should instead be able to define infix functions (i.e., operators) have a form like, O, just as colons, no control characters, no parens, bracketts, or braces, no backslash, and surrounded by colons. Also require white-space separation from everything else. So one could define :+: to add matrices, etc., and as these would really be functions, they should follow the normal overloading rules of functions. This would allow them to be easily parsed, would distinguish them clearly from the standard operators, and would provide the majority of the notational compactness that normal operators provide. The fact that A :+: B would be syntactic sugar for A.add (B) is minor, but convenient. As to precedence ... they should probably bind more strongly than any other operator, and all to the same degree. If you want to get fancy, you'ld need to use parentheses.Now this idea has a lot of merit! Thanks for posting it. I *like* it being clearly distinguishable from the native operators.
Aug 17 2001
Walter wrote:Charles Hixson wrote in message <3B7D2C6B.4040702 earthlink.net>...Again, I think I read in Stroustrup the suggestion that a language that was happy using unicode as the source charset could allow you to overload "funny characters" as operators. This would let you use, e.g., u22C5 ("dot operator") for matrix multiply, u22C5 and u00D7 ("multiplication sign") for dot and cross products of vectors, u221A, u221B, u221C for square, third, and fourth roots, etc. This lets a huge variety of obscure branches of mathematics use a "native notation", including notations that haven't been invented yet. You do need a way of describing the prefix/postfix/infixity and possibly precedence and binding of such new operators, though.[1] Of course, adopting this rule leads you down a slippery slope back down to the plus sign. I'd be very happy to have you wind up at the bottom of that slippery slope and decide that C++-style operator overloading is acceptable for D. All language features are abusable; don't let the design of iostream sour you on the concept of operator overloading. -Russell B [1] I didn't like the "dummy operand" solution for ++/-- in C++, though. How about ++operator and operator++ ?...So one could define :+: to add matrices, etc., and as these would really be functions, they should follow the normal overloading rules of functions. This would allow them to be easily parsed, would distinguish them clearly from the standard operators, and would provide the majority of the notational compactness that normal operators provide. The fact that A :+: B would be syntactic sugar for A.add (B) is minor, but convenient. As to precedence ... they should probably bind more strongly than any other operator, and all to the same degree. If you want to get fancy, you'ld need to use parentheses.Now this idea has a lot of merit! Thanks for posting it. I *like* it being clearly distinguishable from the native operators.
Aug 17 2001
Russell Bornschlegel wrote in message <3B7DC29E.3415E464 estarcion.com>...Of course, adopting this rule leads you down a slippery slope back down to the plus sign. I'd be very happy to have you wind up at the bottom of that slippery slope and decide that C++-style operator overloading is acceptable for D. All language features are abusable; don't let the design of iostream sour you on the concept of operator overloading.I admit that implementing iostream and just the way it *looks* turned me off. All those << and >> just rubs me the wrong way.[1] I didn't like the "dummy operand" solution for ++/-- in C++, though. How about ++operator and operator++ ?Why not just say ++ and -- are not overloadable <g> ?
Aug 17 2001
"Walter" <walter digitalmars.com> wrote in message news:9lkiqi$2pqd$1 digitaldaemon.com...Russell Bornschlegel wrote in message <3B7DC29E.3415E464 estarcion.com>...If that were the case, STL iterators would be much harder to use... as normal pointers provide ++ and -- but not .inc() and .dec() or whatever. Not providing operator overloading at the time you decide to provide templates could lead to problems. Keeping an eye out for templates could be a large factor in the design of your operator overloading solution... otherwise there'd be no way to design a template that could accept either standard numeric types or user-defined types interchangeably, as the user-defined classes would end up having to use a different syntax for operators such as :+: or whatever, so the template for a + b wouldn't match operator :+:. I've written and used enough matrix and vector classes to know how valuable operator overloading is... so of course I want them in the D language. But I also want templates at some point so don't rush to conclusions about how operator overloading should work. One solution for this may be that if you specify :+:, and there's no match for the types involved for a user-redefined operator :+:, the compiler should try to apply the normal operator + instead. Same for all other operators D has built in. :*: => * , etc. Then inside templates you would always use :+:. However that will surely make templates even uglier than they would have to be already. I'd rather just be able to overload any identifier or series of symbols not allowing white space and not mixing digits or alphanumerics together with symbols, and specify whether it's infix (binary) or prefix (unary) or postfix (unary). Sure, people can misuse this. Those are the kind of things people will both praise and curse D for. For those who've been shot in the foot and are against operator overloading, I have this to say: if you can't tolerate being shot in the foot, you may be in the wrong profession. ;) SeanOf course, adopting this rule leads you down a slippery slope back down to the plus sign. I'd be very happy to have you wind up at the bottom of that slippery slope and decide that C++-style operator overloading is acceptable for D. All language features are abusable; don't let the design of iostream sour you on the concept of operator overloading.I admit that implementing iostream and just the way it *looks* turned me off. All those << and >> just rubs me the wrong way.[1] I didn't like the "dummy operand" solution for ++/-- in C++, though. How about ++operator and operator++ ?Why not just say ++ and -- are not overloadable <g> ?
Oct 29 2001
"Sean L. Palmer" <spalmer iname.com> wrote in message news:9rj3u0$2pf2$1 digitaldaemon.com...For those who've been shot in the foot and are against operatoroverloading,I have this to say: if you can't tolerate being shot in the foot, youmaybe in the wrong profession. ;) SeanOwwww! -Walter
Oct 30 2001
Walter wrote:Now this idea has a lot of merit! Thanks for posting it. I *like* it being clearly distinguishable from the native operators.I don't see that resolving an overloaded operator is any easier just because you have colons around it to distinguish it... the parser generates a tree using expression rules for +, * etc., so no extra complexity there. The code generator then has to decide whether to emit an integer addition for int + int, a floating point addition for float + float, or look up a function in the symbol table for user-defined cases. You still have to choose int+int vs. float+float, so the extra complexity is surely minimal. It's another story if, as in Algol 68, you can define your own operator tokens and change operator priorities, or as in Ada where you can overload based on the result type rather than the parameter types, but I hope no-one's suggesting that... :-) ----------------------------------------------------------------- John English | mailto:je brighton.ac.uk Senior Lecturer | http://www.it.bton.ac.uk/staff/je Dept. of Computing | ** NON-PROFIT CD FOR CS STUDENTS ** University of Brighton | -- see http://burks.bton.ac.uk -----------------------------------------------------------------
May 02 2002
Yes overloaded operators are useful. Creating operators like Charles Hixson sugest can be usefull as well ! Me if i use D langage in the future, i would like to have both. In fact Charles Hixson's way it looks like an other way of calling functions with the first argument placed before the name of the function and the second argument placed after the name of the function and no parenthesis. why not any function with one or two arguments be able to be called that way ? Roland Charles Hixson a écrit :Overloaded operators can be quite useful, but perhaps the standard operators shouldn't be overloadable. Perhaps one should instead be able to define infix functions (i.e., operators) have a form like, O, just as colons, no control characters, no parens, bracketts, or braces, no backslash, and surrounded by colons. Also require white-space separation from everything else. So one could define :+: to add matrices, etc., and as these would really be functions, they should follow the normal overloading rules of functions. This would allow them to be easily parsed, would distinguish them clearly from the standard operators, and would provide the majority of the notational compactness that normal operators provide. The fact that A :+: B would be syntactic sugar for A.add (B) is minor, but convenient. As to precedence ... they should probably bind more strongly than any other operator, and all to the same degree. If you want to get fancy, you'ld need to use parentheses.
Aug 23 2001
Walter wrote:I agree that operator overloading can be used for matrix and vector classes, in fact, the first user of my C++ compiler used it to develop a matrix class! The results were disappointing, though. It's amazingly difficult to write a good class that overloads operators.There are lots of other common applications, too; consider a Date class. In Java, the lack of operator overloading means that to add a number of days to a Date you have to write this: d.setDate( d.getDate() + n ); and to compare dates: if (d1.before(d2)) ... In "sensible" languages (C++, Ada etc.), you can overload operators so that you can say "if (d1 + n < d2) ...", which IMHO is a hell of a lot more readable. ----------------------------------------------------------------- John English | mailto:je brighton.ac.uk Senior Lecturer | http://www.it.bton.ac.uk/staff/je Dept. of Computing | ** NON-PROFIT CD FOR CS STUDENTS ** University of Brighton | -- see http://burks.bton.ac.uk -----------------------------------------------------------------
May 02 2002
"John English" <je brighton.ac.uk> wrote in message news:3CD14339.3146AD65 brighton.ac.uk...There are lots of other common applications, too; consider a Date class. In Java, the lack of operator overloading means that to add a number of days to a Date you have to write this: d.setDate( d.getDate() + n ); and to compare dates: if (d1.before(d2)) ...I don't know why Java decided to do dates that way, but I don't think it's the right way. In D (as in C, Javascript, etc.) a date is represented by an arithmetic type. Comparisons, math, etc., on dates are all ordinary arithmetic operations on an ordinary arithmetic type. The only time it has meaning as a date is when it is converted to or from a string, or when things like "day of week" is extracted from it.In "sensible" languages (C++, Ada etc.), you can overload operators so that you can say "if (d1 + n < d2) ...", which IMHO is a hell of a lot more readable.Your are right, but I don't think Date is the best example <g>.
May 06 2002
"Walter" <walter digitalmars.com> wrote in message news:ab5rnl$1o5t$1 digitaldaemon.com...I don't know why Java decided to do dates that way, but I don't think it'sI guess it's because you can then make properties like month, day, dayOfWeek etc, all being members of class Date, rather than global functions. With operator overloading, it would make sence.
May 06 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:ab63ke$20j7$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:ab5rnl$1o5t$1 digitaldaemon.com...it'sI don't know why Java decided to do dates that way, but I don't thinkI guess it's because you can then make properties like month, day,dayOfWeeketc, all being members of class Date, rather than global functions. With operator overloading, it would make sence.In MFC Microsoft defined a COleDateTime class which does just that. It contains a member field which holds a variable of type DATE (which is an OLE type that maps to a float) and has all kinds of helper functions and operators defined to ease working with it. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
May 06 2002
Walter wrote:"John English" <je brighton.ac.uk> wrote in message news:3CD14339.3146AD65 brighton.ac.uk...So you can multiply and divide dates? Hmm... I wonder what 8 May 2002 divided by 3 is? ----------------------------------------------------------------- John English | mailto:je brighton.ac.uk Senior Lecturer | http://www.it.bton.ac.uk/staff/je Dept. of Computing | ** NON-PROFIT CD FOR CS STUDENTS ** University of Brighton | -- see http://burks.bton.ac.uk -----------------------------------------------------------------There are lots of other common applications, too; consider a Date class. In Java, the lack of operator overloading means that to add a number of days to a Date you have to write this: d.setDate( d.getDate() + n ); and to compare dates: if (d1.before(d2)) ...I don't know why Java decided to do dates that way, but I don't think it's the right way. In D (as in C, Javascript, etc.) a date is represented by an arithmetic type. Comparisons, math, etc., on dates are all ordinary arithmetic operations on an ordinary arithmetic type. The only time it has meaning as a date is when it is converted to or from a string, or when things like "day of week" is extracted from it.
May 08 2002
John English wrote:So you can multiply and divide dates? Hmm... I wonder what 8 May 2002 divided by 3 is?You can't really multiply or divide a date...but you can do so for a time. So you either see a Date as "the time since some epoch," or as a special addable value, where 2 of the 3 elements in any equation must be Date and the other is a Time: Date = Date + Time Time = Date - Date -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
May 08 2002
"John English" <je brighton.ac.uk> ha scritto nel messaggio news:3CD90494.484154AF brighton.ac.uk...So you can multiply and divide dates? Hmm... I wonder what 8 May 2002 divided by 3 is?It's the wrong question. The good is: What 8 May 2002 divided by 16 Oct 1992 is? And sin(8 May 2002) * cos(16 Oct 1992) ? :-) Ciao
May 09 2002
"Roberto Mariottini" <rmariottini lycosmail.com> wrote in message news:abd9va$2osk$1 digitaldaemon.com..."John English" <je brighton.ac.uk> ha scritto nel messaggio news:3CD90494.484154AF brighton.ac.uk...What is the square root of -4? Some operations on dates or times do not make sense, but the same goes for ordinary numbers. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mailSo you can multiply and divide dates? Hmm... I wonder what 8 May 2002 divided by 3 is?It's the wrong question. The good is: What 8 May 2002 divided by 16 Oct 1992 is? And sin(8 May 2002) * cos(16 Oct 1992) ? :-) Ciao
May 09 2002
OddesE wrote:What is the square root of -4?It's 2j. I'm going to fork this off...it gave me a cool ponder. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
May 09 2002
John Fletcher wrote:Comment: For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable. John FletcherGotta agree wholeheartedly with this. If you are doing any numerical computation, then using infix operators is an enormous convenience. This is one (only one, there are others:-) of the problems with Java IMO. -- Cheers, Brendan. ---------------------------------------------------------------------------- Brendan McCane Email: mccane cs.otago.ac.nz Department of Computer Science Phone: +64 3 479 8588/8578. University of Otago Fax: +64 3 479 8529 Box 56, Dunedin, New Zealand. There's only one catch - Catch 22.
Aug 16 2001
Brendan McCane wrote:John Fletcher wrote:Remember, from a distant perspective *all* "operators" are "syntactic sugar"! (A "convenience" as mentioned above.) How's that? Well, let's look at an arbitrary complex expression in C, one with several operators: this.that.pointer_to->something_else = z**(2*pi) / (x ^ 0xff); Let's move it all to functions: memberOf(deRef(memberOf(memberOf(this, that),pointer_to)), something_else) = div(pow(z, times(2, pi)), xor(x, 0xff)); Not a single operator in the line, and nearly completely unreadable. (Should I have used RPN instead?) Where to go from here? Well, the isomorphism is visible, at the very least. And that's the key. Though I'm a D newbie, one resolution path comes from the separatiion of the syntactic and semantic elements of the language. While pre-processing is not a "feature" of D, I'm sure some entreprising individuals will hack the parsers in a way that will allow arbitrary operator creation (and overloading), done under the guise of a simple mapping operation. Of course, a tool such as M4 may be easier to use, or even cpp or sed! For example, create the file "myoperators.d" with the following contents: import math; import operatorLib; Operator("**", <double LHS>, <double RHS>, "pow(LHS,RHS)"); Overload("^", <double LHS>, <double RHS>, "pow(LHS,RHS)"); Then, in D code, do an "import myoperators". The first definition would create the new operator "**", and the second would overload the "^" (XOR) operator for doubles. (The assignment versions "**=" and "^=" could be implicitly defined whenever the LHS and RHS are of the same type.) This would map expressions of the form "A**B" and "A^B" to the string "pow(A,B)" when A and B are doubles (where "LHS" and "RHS" are placeholder tokens for each side of the operator). Once the code is generated, the compiler would catch type mismatch errors as usual. Ideally, any such errors would be mapped back to the original text, and not to the replacement (a common problem with C macros). Hence the need to hack the parsers (especially if things like operator precedence are to be implemented simply). [Actually, I'd vote to eliminate multiple levels of operator precedence! Let's make everything Left-to-Right, and use parens as needed to make precedence explicit.] This could possibly be done via an enhanced module interface, allowing us to avoid many problems by simply forbidding operator definitions to be used within the files containing their definition. I feel the many of the problems with (and objections to) C++ operator creation and overloading appear to reduce to management issues. By making the process simpler and explicit (via implementation as a true dynamic language extension, rather than as a textual substitution) we may be able to control and manage the beast. I'm not yet familiar enough with D and its parsers to make a specific recommendation. Help? Of course, Lisp and Forth adherents will point out the difficulties with "operator explosion", where so many custom operators are implemented that the language morphs into something quite implementation-specific, and completely impenetrable even to language experts. Let's not make operator creation and overloading too easy! But, within reasonable restrictions, it should be made possible. How can we get what we need from operator creation and overloading with minimal fuss, safety, readability and reliability? The C++ way has well documented difficulties and is easy to misuse, but it can be made to work. Remember, D already provides overloading for the common math operators over the intrinsic numeric types. Can we allow the D programmer to extend this on their own, or must the whole concept be scrapped? If there really is no "suitable" way to do all this within D itself, then at least we'll always have functions and M4... -BobCComment: For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable. John FletcherGotta agree wholeheartedly with this. If you are doing any numerical computation, then using infix operators is an enormous convenience. This is one (only one, there are others:-) of the problems with Java IMO.
Aug 16 2001
My 2c: Operator overlaoding is purely syntactic sugar, it adds no new functionality to a language. In many cases it makes the code harder to read and to debug. It is aimed at the problem domain of science/math modelling, which makes up a rather small part of computing today.the difference between a += b; and a.append(b); is minor and really not worth adding big features to the language to support.quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable.
Sep 09 2001
Anthony Steele wrote:My 2c: Operator overlaoding is purely syntactic sugar, it adds no new functionality to a language. In many cases it makes the code harder to read and to debug. It is aimed at the problem domain of science/math modelling, which makes up a rather small part of computing today.a) It's not a big feature if you already have overloaded functions. When done properly it's rather simple to replace operator calls with a rewrite into functional notation. It's just harder for people to get correct. b) You can be obfuscated with nearly any language feature. Just because some people have gone hog-wild is no reason to denigrate the whole concept. OTOH, I do support a clear distinction between user defined operators and system defined operators. But I also know of languages that don't support that disctinction, and which don't suffer excessively because of that. c) The math folks have had longer to develop their opeartors. String processing might be expected to develop standard operators over time. Presumable other domains would also be appropriate. Certainly sets have readily defineable operators, and it would be desireable for them to be useable. And one would, e.g., want to use the same operators for sets composed of lists and for sets generated by rules, though of course the implementations would need to be quite different. The extends into SQL processing (not such a small field anymore, perhaps?). etc. And that's just what occurs off the top of my head. I'm sure that most people have some domain that they would use operators with, if they were possible. And the domains are probably not identical. If you are going to do a small isolated operation, then you are correct. The amount gained by overloaded operators is small. But if one is composing operations on data structrues, then the operation will not necessarily be small. To take a minor and simple example: strVal = salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: title can probably be understood without any explanation. Replacing it with the re-written code: strVal = salute.append (firstName.append (midInit.append (lastName.append(perhapsComma.append(jr_etc.append (titlePunct.append (title... is not only more difficult to read ... but I didn't finish it becuase I didn't want to count how many parenthesis to put at the end. (And on looking it over, I corrected one typo of a missing open paren...nothing similar happened with the first version.)the difference between a += b; and a.append(b); is minor and really not worth adding big features to the language to support.quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable.
Sep 10 2001
strVal = salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: titleWell = will also be most like an overload assignment operator so: strVal :=: salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: title I can already estimate that people will not be pleased to realise that a = b :+: c; will do something fundamently different than, a :=: b :+: c; This results into something error prone :/
Sep 10 2001
Axel Kittenberger wrote:strVal = salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: titleWell = will also be most like an overload assignment operator so: strVal :=: salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: title I can already estimate that people will not be pleased to realise that a = b :+: c; will do something fundamently different than, a :=: b :+: c; This results into something error prone :/
Sep 10 2001
Axel Kittenberger wrote:Sorry about the empty reply. If you don't want it to mean something "fundamentally different", then don't define it that way. You could also define append to mean something silly, but we generally suppose that you won't. And the = was inteneded to be the standard string-to-string assignment, so I didn't redefine it. But append is only annalogous to addition, so it was appropriate to use an analogous operator, but not appropriate to re-define the original addition. Now I would admit that it was reasonable to use to + operator for all purely numeric types, providing that the implemented transitivity, commutativity, and association. This would include matricies, vectory, etc. But notice that this doesn't extend to multiplication, as the multiplication of structured numeric types doesn't obey commutativity. I.e., A * B != B * A for matricies (except in special cases.) Similarly, string concatenation doesn't obey association: "a" + "b" != "b" + "a" so the simple + operation is the wrong choice. Etc. Frequently an operation can be defined appropriately only for the classes that implement "some interface": E.g., if Comparable is implemented then the operators: < <= == >= > != are defineable. If a particular class implements Comparable, then all of its decentant classes should be able to use those operators (well, D doesn't seem to provide a way of hiding them). But this doesn't seem to me to mean that they should necessarily use the same ordering. Actually, this highlights one of the weaknesses in the class inheritance structuring of programs. Frequently a praticular chunk of data, stored in a particular structure, will need to be accessed in more than one order. For example, databases will generally use more than one index to access the data in the files. Some of these indexes (most actually) will only pull up a part of the data. So one defines views over the data. Now imagine that the database is in memory. Probably it would be in an array, but the index would not be significant, except as a accessing method. Stepping through on the index would access all of the data in sequence, but not in any particularly useful sequence. So one would want to define several different views of the data, which would allow one to access the data in different orders (and pull up different pieces of it). Some of them would be read only views. Etc. This seems to map more easily onto structs and functions then onto classes and inheritance. And yet these aren't simple things. One would often want them to exhibit fairly complex behaviors. So one would end up implementing a class for each record type. And even fairly closely related record types would have difficulty defining an inheritance relationship that implied mixing their functionality with that of another record type. Two identical fields would be more likely to be a join key field than a field for sorting the two kinds of record on, e.g. So they typical class building operation would involve joining pieces of the two record types together into one. But this is a prohibited variety of inheritance. And in any case it would frequently be implemented by building a list of correspondences between the two record categories, and then for each funciton call on an item in the list, forwarding the call to the appropriate record type for processing. So this view of "multiple inheritance" is a bit different than the normal programming language model. This is viewing multiple inheritance as rather like a SQL Select statement, with multiple files. And one would want the join operator to be able to work on all of the record types defined. I seem to have veered a bit from operator overloading. My appologies. But it doesn't feel less important because of that.strVal = salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: titleWell = will also be most like an overload assignment operator so: strVal :=: salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: title I can already estimate that people will not be pleased to realise that a = b :+: c; will do something fundamently different than, a :=: b :+: c; This results into something error prone :/
Sep 10 2001
If you don't want it to mean something "fundamentally different", then don't define it that way. You could also define append to mean something silly, but we generally suppose that you won't. And the = was inteneded to be the standard string-to-string assignment, so I didn't redefine it.Well fundamentally different was a false, it's even worse than that: it's slightly different a = b; will assign the object a to point to b and to be a synonym for it in future a :=: b; will take the contents of b and assign/copy them to a; Now take folowing hypothetical code: a = b; b.printf("%d", 7); writeln(b); vs: a :=: b; b.printf("%d", 7); writeln(b); The results will be different, not the language is wrong that way, I just want to point that this way we're just creating a caveat, a hole thounds will fall into. Well supposed ten thousend people will use it :) so let's better say 25% of users. How many people debugged hour for hour again and again for write '=' in if's until compilers learned to warn there?But append is only annalogous to addition, so it was appropriate to use an analogous operator, but not appropriate to re-define the original addition. Now I would admit that it was reasonable to use to + operator for all purely numeric types, providing that the implemented transitivity, commutativity, and association. This would include matricies, vectory, etc. But notice that this doesn't extend to multiplication, as the multiplication of structured numeric types doesn't obey commutativity. I.e., A * B != B * A for matricies (except in special cases.) Similarly, string concatenation doesn't obey association: "a" + "b" != "b" + "a" so the simple + operation is the wrong choice. Etc.Okay I agree, but an optimizer should know if an user operation is associative, or communative, or ummm. I forget now the name of the last one from a = b, and b = c follows a = c. Now you define the syntax for telling this the compiler, a checker that checks if this is true, and an optimizer that's able to handle that :o)Now imagine that the database is in memory. Probably it would be in an array, but the index would not be significant, except as a accessing method. Stepping through on the index would access all of the data in sequence, but not in any particularly useful sequence. So one would want to define several different views of the data, which would allow one to access the data in different orders (and pull up different pieces of it). Some of them would be read only views. Etc.In example, a hashmap, right?This seems to map more easily onto structs and functions then onto classes and inheritance. And yet these aren't simple things. One would often want them to exhibit fairly complex behaviors. So one would end up implementing a class for each record type. And even fairly closely related record types would have difficulty defining an inheritance relationship that implied mixing their functionality with that of another record type. Two identical fields would be more likely to be a join key field than a field for sorting the two kinds of record on, e.g. So they typical class building operation would involve joining pieces of the two record types together into one. But this is a prohibited variety of inheritance. And in any case it would frequently be implemented by building a list of correspondences between the two record categories, and then for each funciton call on an item in the list, forwarding the call to the appropriate record type for processing. So this view of "multiple inheritance" is a bit different than the normal programming language model. This is viewing multiple inheritance as rather like a SQL Select statement, with multiple files. And one would want the join operator to be able to work on all of the record types defined.Reading this, and thinking what I touched in the past, only one world hits my mind regarding this: Deplhi! Am I right? I guess many things where handled this way there like the Tables, Lists, and it's wonderfull interface to SQL. Well wasn't this why polymorphism was introduced? (virtual functions) - Axel
Sep 10 2001
Axel Kittenberger wrote:...A hashmap doesn't imply an ordering. I suppose that you can sort the keys, but then what's the gain in making it a hashmap rather than, say, a balanced tree, which would inherently have the order present?Now imagine that the database is in memory. Probably it would be in an array, but the index would not be significant, except as a accessing method. Stepping through on the index would access all of the data in sequence, but not in any particularly useful sequence. So one would want to define several different views of the data, which would allow one to access the data in different orders (and pull up different pieces of it). Some of them would be read only views. Etc.In example, a hashmap, right?..Virtual functions don't adequately handle this. Even SQL only handles a portion of it. This comes more out of databases than any programming language that I've encountered. MS Basic ends up wrapping all the data definitions into a string class that's interpreted at run time. Not a good answer. Most languages seem to just ignore the problem. Python allows one to import an external B+Tree (SleepyCatDB) with an interface that's the same as a hashtable (Dictionary) even though it is inherently sorted. It works well because a B+Tree supports random access quite well. But Python allows one to dynamically determine the members of a class. This is probably inappropriate for D, but I'm not sure what the appropriate way is. And, I notice that I'm suddenly back on the thread again. Python handles the mapping by re-defining the dictionary access operators, so that one can access the B+Tree as if it were a dictionary. There are, however, also methods that permit the definition of indicies within the database, etc. But a dictionary that gets too large, or which suddenly needs to become persistent, can be migrated to a database with only the change of a few lines in the program.So this view of "multiple inheritance" is a bit different than the normal programming language model. This is viewing multiple inheritance as rather like a SQL Select statement, with multiple files. And one would want the join operator to be able to work on all of the record types defined.Reading this, and thinking what I touched in the past, only one world hits my mind regarding this: Deplhi! Am I right? I guess many things where handled this way there like the Tables, Lists, and it's wonderfull interface to SQL. Well wasn't this why polymorphism was introduced? (virtual functions) - Axel
Sep 10 2001
A hashmap doesn't imply an ordering. I suppose that you can sort the keys, but then what's the gain in making it a hashmap rather than, say, a balanced tree, which would inherently have the order present?No didn't mean sorting, but you've also two ways to access a hashmap, a) iterate through all entries without any order, b) fast-get a specifc entry by it's key.
Sep 10 2001
Axel Kittenberger wrote:associative, or communative, or ummm. I forget now the name of the last one from a = b, and b = c follows a = c.transitive
Feb 04 2002
Charles Hixson wrote:b) You can be obfuscated with nearly any language feature. Just because some people have gone hog-wild is no reason to denigrate the whole concept. OTOH, I do support a clear distinction between user defined operators and system defined operators. But I also know of languages that don't support that disctinction, and which don't suffer excessively because of that.Just for arguments sake, if you had distinct user defined operators, and if we ever get some form of generic programming into the language, how would you suggest writing generic code that could work both for built in type like floats, and user defined type like vectors? You can use '==' on user types, and you (presumably) can't use ':==:' (or what ever we make) on built ins. I'm all for overloads, and I don't mind differentiated between user types and built in type, but I don't want use this to paint us into a corner with regard to generic programming. Dan
Sep 10 2001
a wrote:Charles Hixson wrote: ... Just for arguments sake, if you had distinct user defined operators, and if we ever get some form of generic programming into the language, how would you suggest writing generic code that could work both for built in type like floats, and user defined type like vectors? You can use '==' on user types, and you (presumably) can't use ':==:' (or what ever we make) on built ins. I'm all for overloads, and I don't mind differentiated between user types and built in type, but I don't want use this to paint us into a corner with regard to generic programming. DanOne could certainly define: operator :==: (left, right : float) { return (left == right); } So I don't see that as a problem.
Sep 11 2001
Charles Hixson wrote:a wrote:And we go from looking at (left == right) and not know if we have built ins or object to seeing (left :==: right) and not know if we are looking at built ins or objects. I think we have just subverted someone else's intentions. DanCharles Hixson wrote: ... Just for arguments sake, if you had distinct user defined operators, and if we ever get some form of generic programming into the language, how would you suggest writing generic code that could work both for built in type like floats, and user defined type like vectors? You can use '==' on user types, and you (presumably) can't use ':==:' (or what ever we make) on built ins. I'm all for overloads, and I don't mind differentiated between user types and built in type, but I don't want use this to paint us into a corner with regard to generic programming. DanOne could certainly define: operator :==: (left, right : float) { return (left == right); } So I don't see that as a problem.
Sep 11 2001
a wrote:Charles Hixson wrote:The built-in operators are still available. So that hasn't been subverted. The :==: has been defined in a way that is seen by the designer as consistent with the way he generally uses the operator, so that hasn't been subverted. I don't understand your point. Whose intentions to do what have been subverted how?a wrote:And we go from looking at (left == right) and not know if we have built ins or object to seeing (left :==: right) and not know if we are looking at built ins or objects. I think we have just subverted someone else's intentions. DanCharles Hixson wrote: ...One could certainly define: operator :==: (left, right : float) { return (left == right); } So I don't see that as a problem.
Sep 12 2001
For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable.Operator overloading as it exists in C++ is unsatisfactory. Unless it can be radically improved I don't see the point of having the feature. I do a lot of graphics programming (for fun, I program Telecommunications software for a living), so I use Vectors a lot. Personally I think they provide a good reason why you *don't* want to use operator overloading. Yes, you can overload +, -, +=, and you can overload * for cross-product, but you can't overload . (period) for dot product. The problems with operator overloading in C++ are: (1) You can only overload the operators that C++ already provides, which deminishes the value of operator overloading, and is a damn pain when there are some extremely common operations for your type which would benefit from it (like a dot operator) (2) You inheirit the precedence of the native operators from C++ which is not always appropriate. (3) Overloading new is just *evil*. It makes debugging a large codebase code a nightmare. (4) It introduces another style for doing very common stuff. One group of programmers does vec.plus(v2) and another does vec + v2. One of the main issues with maintaining any large code base is uniformity of style. The more you can encourage people to express simple concepts in the same way, the better. Personally I think that overloading is not worth the hype and tends to obfuscate code. If you *must* implement it, don't do it unless you can use any operators you like (regardless of whether the language supports them natively) and you must be able to specify your own precedence (that'd be a fun compiler to write!). Peter.
Aug 17 2001
kaffiene wrote:Personally I think that overloading is not worth the hype and tends to obfuscate code. If you *must* implement it, don't do it unless you can use any operators you like (regardless of whether the language supports them natively) and you must be able to specify your own precedence (that'd be a fun compiler to write!). Peter.I know of a C++ compiler (SALFORD C++ http://www.suns.salford.ac.uk/compilers/salfordc/index.shtml) which has a pragma to allow the definition of new operators and specify the position in the precedence. It also produces very lint like error messages. I could not find a user group. John Fletcher
Aug 17 2001
John Fletcher wrote:kaffiene wrote:Algol 68 did this too, many years ago. ----------------------------------------------------------------- John English | mailto:je brighton.ac.uk Senior Lecturer | http://www.it.bton.ac.uk/staff/je Dept. of Computing | ** NON-PROFIT CD FOR CS STUDENTS ** University of Brighton | -- see http://burks.bton.ac.uk -----------------------------------------------------------------Personally I think that overloading is not worth the hype and tends to obfuscate code. If you *must* implement it, don't do it unless you can use any operators you like (regardless of whether the language supports them natively) and you must be able to specify your own precedence (that'd be a fun compiler to write!). Peter.I know of a C++ compiler (SALFORD C++ http://www.suns.salford.ac.uk/compilers/salfordc/index.shtml) which has a pragma to allow the definition of new operators and specify the position in the precedence. It also produces very lint like error messages. I could not find a user group.
May 03 2002
For LX, I invented the "written" notation. In D-like syntax, it would be: matrix Add(matrix M, matrix N) written M+N { ... } One benefit is that it allows you to define N-way operators: matrix MultiplyAndAdd(matrix A, float B, matrix C) written A*B+C { ... } There are many cases where this is really simpler or more efficient than two-way operators. Another slight extension offered by LX is to allow the definition of named infix operators (which all share the same, lowest priority): int And(int A, int B) written A and B; This is much easier to define and implement than it sounds. This being presented, I can discuss your e-mail in more details... kaffiene wrote:The point being that a very large portion of C++ code out there uses it in one form or another. I take this as an indication that it's probably useful to some. Avoid the common pitfall of thinking: "I don't need it, therefore nobody needs it."For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable.Operator overloading as it exists in C++ is unsatisfactory. Unless it can be radically improved I don't see the point of having the feature.I do a lot of graphics programming (for fun, I program Telecommunications software for a living), so I use Vectors a lot. Personally I think they provide a good reason why you *don't* want to use operator overloading. Yes, you can overload +, -, +=, and you can overload * for cross-product, but you can't overload . (period) for dot product.WIth the written approach, at least, you could define float DotProduct(vector A, vector B) written A dot B (As a matter of fact, the LX compiler would let you override A.B that way, if memory serves me right, but it might not be possible in the general framework of the D semantics)The problems with operator overloading in C++ are: (1) You can only overload the operators that C++ already provides, which deminishes the value of operator overloading, and is a damn pain when there are some extremely common operations for your type which would benefit from it (like a dot operator)As a matter of fact, overloading the . operator was a hot debate within the C++ committee. Microsoft was all in favor of it. I personally consider a mistake that it was not allowed, because it disabled a whole class of "smart objects". Anyway, this doesn't have to be the case in D.(2) You inheirit the precedence of the native operators from C++ which is not always appropriate.That's not a problem, that's a feature. The compiler would be unable to parse expressions correctly if operator precedence changed. If the compiler can't parse it, the human brain probably would have trouble too. For instance, say you have A+B*C, with operators that make both (A+B)*C and A+(B*C) be valid, with different meanings... what do you select? If you enable variable-precedence operators, you end up with a real compile-time nightmare, at best. This being said, the written approach allows you to redefine priorities, if you are really nasty. glop Reorder(glop A, glop B, glop C) written A+B*C { return (A+B)*C; // Yuck yuck }(3) Overloading new is just *evil*. It makes debugging a large codebase code a nightmare.The LX compiler uses a form of garbage collection. The first thing it needs to do is to know what objects to collect. operator new tells me precisely that. The problem with C++ features in general is not that they are necessarily bad, but that people want to show off by using them at the wrong place and time. There are C++ features that are bad (declaration syntax, lookup rules). But definitely not operator overloading.(4) It introduces another style for doing very common stuff. One group of programmers does vec.plus(v2) and another does vec + v2. One of the main issues with maintaining any large code base is uniformity of style. The more you can encourage people to express simple concepts in the same way, the better.The absence of operator overloading is bad, because it introduces yet another style for doing very common stuff. For instance, to add two integers, I write A+B, but to add two vectors, I write A.add(B). One of the main issues with maintaining any large code base is uniformity of style. The more you can encourage people to express simple concepts in the same way, the better. Actually, this is more serious than you think. You just CAN'T WRITE TEMPLATE CODE if the form in which you express things is not common.Personally I think that overloading is not worth the hype and tends to obfuscate code. If you *must* implement it, don't do it unless you can use any operators you like (regardless of whether the language supports them natively) and you must be able to specify your own precedence (that'd be a fun compiler to write!).Personally, I think that overloading tends to less obfuscated code than most other notations. Christophe
Aug 17 2001
"Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B7D2B88.C079FD16 earthlink.net...For LX, I invented the "written" notation. In D-like syntax, it would be: matrix Add(matrix M, matrix N) written M+N { ... } One benefit is that it allows you to define N-way operators: matrix MultiplyAndAdd(matrix A, float B, matrix C) written A*B+C { ... } There are many cases where this is really simpler or more efficient than two-way operators. Another slight extension offered by LX is to allow the definition of named infix operators (which all share the same, lowest priority): int And(int A, int B) written A and B; This is much easier to define and implement than it sounds. This being presented, I can discuss your e-mail in more details...That's really nice.vectors,For numerical computing it is convenient to define classes e.g.canmatrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable.Operator overloading as it exists in C++ is unsatisfactory. Unless itonebe radically improved I don't see the point of having the feature.The point being that a very large portion of C++ code out there uses it inform or another. I take this as an indication that it's probably useful to some. Avoid the common pitfall of thinking: "I don't need it, thereforenobodyneeds it."That is not my point of view at all - my view is that one should avoid multiplying the number of ways in which you can achieve the same result - it makes for a code maintainence headache. I think C++ is supremely guilty of this. Perl is an example of a language which will provide a zillion solutions to a given problem. It is also a language that you wouldn't want to maintain a large code base in. I think these two facts are related.TelecommunicationsI do a lot of graphics programming (for fun, I programcross-product,software for a living), so I use Vectors a lot. Personally I think they provide a good reason why you *don't* want to use operator overloading. Yes, you can overload +, -, +=, and you can overload * forThat really is nice.but you can't overload . (period) for dot product.WIth the written approach, at least, you could define float DotProduct(vector A, vector B) written A dot B(As a matter of fact, the LX compiler would let you override A.B that way,ifmemory serves me right, but it might not be possible in the generalframeworkof the D semantics)thereThe problems with operator overloading in C++ are: (1) You can only overload the operators that C++ already provides, which deminishes the value of operator overloading, and is a damn pain whenfromare some extremely common operations for your type which would benefitthe C++it (like a dot operator)As a matter of fact, overloading the . operator was a hot debate withincommittee. Microsoft was all in favor of it. I personally consider amistakethat it was not allowed, because it disabled a whole class of "smartobjects".Anyway, this doesn't have to be the case in D.is(2) You inheirit the precedence of the native operators from C++ whichparsenot always appropriate.That's not a problem, that's a feature. The compiler would be unable toexpressions correctly if operator precedence changed. If the compilercan'tparse it, the human brain probably would have trouble too. For instance,sayyou have A+B*C, with operators that make both (A+B)*C and A+(B*C) bevalid,with different meanings... what do you select? If you enable variable-precedence operators, you end up with a real compile-timenightmare,at best.The rhetoric of operator overloading is that it is better because it more accurately reflects the normal mathematical notation of operations in a given context. If operator overloading must enforce a given precedence then this is not true, is it? If I define a * operation on Vectors for cross-product, then I want it to have the same precedence as . for dot product. And why should a vector cross product be arbitrarily forced to haver higher or lower precedence that other operators such as addition? No such limitation is imposed on the mathematical notation. Having to put up with it because its a hangover from how the compiler handles basic types doesn't seem like a very noble, clean or advanced notion, does it?This being said, the written approach allows you to redefine priorities,if youare really nasty. glop Reorder(glop A, glop B, glop C) written A+B*C { return (A+B)*C; // Yuck yuck }needs to(3) Overloading new is just *evil*. It makes debugging a large codebase code a nightmare.The LX compiler uses a form of garbage collection. The first thing itdo is to know what objects to collect. operator new tells me preciselythat.The problem with C++ features in general is not that they are necessarilybad,but that people want to show off by using them at the wrong place andtime.There are C++ features that are bad (declaration syntax, lookup rules).Butdefinitely not operator overloading.of(4) It introduces another style for doing very common stuff. One groupmainprogrammers does vec.plus(v2) and another does vec + v2. One of themoreissues with maintaining any large code base is uniformity of style. Theanotheryou can encourage people to express simple concepts in the same way, the better.The absence of operator overloading is bad, because it introduces yetstyle for doing very common stuff. For instance, to add two integers, IwriteA+B, but to add two vectors, I write A.add(B). One of the main issues with maintaining any large code base is uniformity of style. The more you can encourage people to express simple concepts in the same way, the better.My point is that you have arithmetic operators for basic types. You have methods calls on objects. This is two ways of doing things. If you add operator overloading that's three. With operator overloading you will still end up with some objects using method calls for add, subtract etc... and other code using operator overloading to achieve exactly the same kind of thing. I *know* that the idea is to have object manipulations looking like operations on simple arithmetic types but the fact is that as soon as you work with more than about three programmers, or inheirit code from someone else or import an API, someone is going to to do the object manipulations in a different way to you. Given that you are commited to having general method calls on objects (obj.method()) deciding to do *all* manipulations that way ensures that there is one and only one style for performing such operations. Choosing to use operator overloading guarantees that as soon as you move beyond your own stylistically/ideologically pure code, some other bugger will mess it up by doing it a different way and you have no choice but to use their idiom. Maintaining C++ code is full of experiences like this - *whichever* style you choose some other code that you have to work with does it radically different. Operator overloading is typically implemented in a very limited way, so it often doesn't do the job of acurately representing the mathematical notation anyway. For example, on vectors I often want to get the magnitude. This is usually represented as ||v|| for magnitude of v. Most operator overloading systems don't cope with such notation, and so cannot fully represent the syntax for working with a given mathematical type properly. It seems to me that you can: (a) Go the C++ route and say that only some predetermined operators may be overloaded and that you have to live with the precedence that they already have - this falls short of the stated goal of making the code syntax look like the mathematical syntax. (b) Go the whole hog and design a system that allows creation of arbitrary operators and overloading the precedence of these and existant operators. This actually *would* allow your system to live up to the rhetoric, but you have to put up with the proliferation of style choices made by each individual programmer you work with, and live with the fact that that a maintenance programmer who is unfamiliar with the given mathematical notation will have an uphill battle to be able to work on your codebase. (c) Don't overload operators at all and have just one idiom for calling methods on objects. I think that there are two extremes - (b) and (c). I believe that (c) is the best idea, but if you must overload operators at least do it properly (b), but personally I think that the negatives (maintenence costs) far outweigh the gains. (a) is a system that does not really do anything well. Peter.
Aug 18 2001
kaffiene wrote:"Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B7D2B88.C079FD16 earthlink.net...As a counterpoint to this, I'll just point out that no one is forced to write obfuscated Perl. The Perl culture promotes it more than it should, but you _can_ write and comment Perl in such a way that it's no harder to read than, say, C. (I'll leave aside the question of whether anyone would want to maintain a large code base in C. :) It's been said before, but bad code can be written in any language. I personally believe that _good_ code can be written in any language, as well. Even Perl.Avoid the common pitfall of thinking: "I don't need it, thereforenobodyneeds it."That is not my point of view at all - my view is that one should avoid multiplying the number of ways in which you can achieve the same result - it makes for a code maintainence headache. I think C++ is supremely guilty of this. Perl is an example of a language which will provide a zillion solutions to a given problem. It is also a language that you wouldn't want to maintain a large code base in. I think these two facts are related.My point is that you have arithmetic operators for basic types. You have methods calls on objects. This is two ways of doing things. If you add operator overloading that's three. With operator overloading you will still end up with some objects using method calls for add, subtract etc... and other code using operator overloading to achieve exactly the same kind of thing.But the first way of doing things, the builtin arithmetic operators, aren't available to classes; the whole point of operator overloading is to allow the _user_ of a class the ability to use the "first way". Philosophically, this makes more sense if your "class implementors" and "class users" are disjoint sets of people; I've never actually worked on a C++ project where this was the case. Blah blah code reuse blah blah. -Russell B
Aug 18 2001
"Russell Bornschlegel" <kaleja estarcion.com> wrote in message news:3B7EB9F9.E9B357EF estarcion.com...kaffiene wrote:result - it"Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B7D2B88.C079FD16 earthlink.net...Avoid the common pitfall of thinking: "I don't need it, thereforenobodyneeds it."That is not my point of view at all - my view is that one should avoid multiplying the number of ways in which you can achieve the sameofmakes for a code maintainence headache. I think C++ is supremely guiltyto athis. Perl is an example of a language which will provide a zillion solutionsagiven problem. It is also a language that you wouldn't want to maintainHaving done it, I'd have to say C is not a bad language to maintain. It doesn't scale well, but it is at least consistent.large code base in. I think these two facts are related.As a counterpoint to this, I'll just point out that no one is forced to write obfuscated Perl. The Perl culture promotes it more than it should, but you _can_ write and comment Perl in such a way that it's no harder to read than, say, C. (I'll leave aside the question of whether anyone would want to maintain a large code base in C. :)It's been said before, but bad code can be written in any language. I personally believe that _good_ code can be written in any language, as well. Even Perl.Sure. It's just a given that when you work in Perl or C++ with more than a couple of people you will start to get code in a multitude of different styles. OTOH, C, Scheme, Java are languages where most people can read most other people's code fairly easily. This is a major factor in maintaining large codebases.stillMy point is that you have arithmetic operators for basic types. You have methods calls on objects. This is two ways of doing things. If you add operator overloading that's three. With operator overloading you willofend up with some objects using method calls for add, subtract etc... and other code using operator overloading to achieve exactly the same kindYes - as I said in my previous mail, I understand that point. My point was that even if you do have operators on classes so users can use them like aritmetical types, you *will* get other code that refuses to user overloading. Hence you *will* get conflicting styles. One codebase will overload operators where it is sensible, one will overload where it is not, another will refuse to oveload even though it might make sense to do so. I fully understand that disallowing operator overloading prevents a user using classes as if they were arithmetic primitives - I am saying that the gain is scant and the cost is too severe. As I also said previously, if we *must* overload operators - at least do it properly and allow for arbitrary operators and precedence so you really can represent the normal mathematical notation for a given type (e.g. ||v|| for vector magnitude). Cheers, Peter.thing.But the first way of doing things, the builtin arithmetic operators, aren't available to classes; the whole point of operator overloading is to allow the _user_ of a class the ability to use the "first way".
Aug 18 2001
kaffiene wrote:I fully understand that disallowing operator overloading prevents a user using classes as if they were arithmetic primitives - I am saying that the gain is scant and the cost is too severe.The gain is scant (if not negative) for something like "cout <<". But it is quite serious for classes that essentially represent arithmetic objects (matrices, vectors, complex numbers, large integers.) In that case, the difference between A+B*C=D+E and A.Add(B.Add(C)).Eq(D.Add(E)) is really significant. In particular in long-term maintenance. My impression is that your own background did not expose you to such "math-oriented" environments. Then, you are right, avoiding operator overloading is probably the right thing to do.As I also said previously, if we *must* overload operators - at least do it properly and allow for arbitrary operators and precedence so you really can represent the normal mathematical notation for a given type (e.g. ||v|| for vector magnitude).No, that is a very bad idea, and not only for technological reasons. Mathematicians invented operator precedence, not compilers (precedence is not an artifact of limited technology, it is a simplifying notation.) I don't know of any context where mathematicians read AxB+C as meaning (Ax(B+C))... But technology also indicates that this is a bad idea, because arbitrary precedences would render most expressions ambiguous. Christophe
Aug 20 2001
Im Artikel <3B80C66E.A86462DB earthlink.net> schrieb "Christophe de Dinechin" <descubes earthlink.net>:kaffiene wrote:I'm pretty sure that by "arbitrary precedence", he didn't mean that there is no precedence, or that the compiler decides what the precedence is, instead that the precedence of a given user-defined operator is user-defined, and that the user (programmer) can choose any precedence he wants for an operator that he defines. -- Sheldon Simms / sheldon semanticedge.comI fully understand that disallowing operator overloading prevents a user using classes as if they were arithmetic primitives - I am saying that the gain is scant and the cost is too severe.The gain is scant (if not negative) for something like "cout <<". But it is quite serious for classes that essentially represent arithmetic objects (matrices, vectors, complex numbers, large integers.) In that case, the difference between A+B*C=D+E and A.Add(B.Add(C)).Eq(D.Add(E)) is really significant. In particular in long-term maintenance. My impression is that your own background did not expose you to such "math-oriented" environments. Then, you are right, avoiding operator overloading is probably the right thing to do.As I also said previously, if we *must* overload operators - at least do it properly and allow for arbitrary operators and precedence so you really can represent the normal mathematical notation for a given type (e.g. ||v|| for vector magnitude).No, that is a very bad idea, and not only for technological reasons. Mathematicians invented operator precedence, not compilers (precedence is not an artifact of limited technology, it is a simplifying notation.) I don't know of any context where mathematicians read AxB+C as meaning (Ax(B+C))... But technology also indicates that this is a bad idea, because arbitrary precedences would render most expressions ambiguous.
Aug 20 2001
"Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B80C66E.A86462DB earthlink.net...kaffiene wrote:userI fully understand that disallowing operator overloading prevents atheusing classes as if they were arithmetic primitives - I am saying thatisgain is scant and the cost is too severe.The gain is scant (if not negative) for something like "cout <<". But itquite serious for classes that essentially represent arithmetic objects (matrices, vectors, complex numbers, large integers.) In that case, the difference between A+B*C=D+E and A.Add(B.Add(C)).Eq(D.Add(E)) is really significant. In particular in long-term maintenance. My impression is that your own background did not expose you to such "math-oriented" environments. Then, you are right, avoiding operator overloading is probably the right thing to do.I majored in Computer Graphics. I quite familiar with both animation for broadcast using raytracing and real time graphics using OpenGL and DirectX. I have written several raytracers. I am about to take up a job with a broadcast graphics company. These are "math-oriented" environments. Your impression is wrong. I noticed that another poster asked you to refrain from sarcasm at one point - I would also ask you to refrain from personal assumptions. If you want to debate the technical merits of a language feature, please do so but don't do it by claiming that people with alternate opinions are ignorant.arbitraryAs I also said previously, if we *must* overload operators - at least do it properly and allow formathematicaloperators and precedence so you really can represent the normalnotnotation for a given type (e.g. ||v|| for vector magnitude).No, that is a very bad idea, and not only for technological reasons. Mathematicians invented operator precedence, not compilers (precedence isan artifact of limited technology, it is a simplifying notation.) I don'tknowof any context where mathematicians read AxB+C as meaning (Ax(B+C))... ButIf you are talking about vectors, then A + B * C is the vector A added to vector B (resulting in a vector) crossed with the vector C (resulting in a vector). This evaluates as (A + B) * C. There you have a context in which the standard arithmetic operator precedence does not hold.technology also indicates that this is a bad idea, because arbitrary precedences would render most expressions ambiguous.*sigh* - please read the history of this thread. My point is that for *new* operators that don't already exist in the language, you need to specify precedence. For example, a Vector class could overload * for cross-product, but C++ doesn't allow overloading . (period) for dot product or ||v|| for magnitude. If you introduce new operators you must be able to specify the precedence. If you change the context of an operator (e.g. * in the vector example above) then the natural precendence of operators may change as well. Peter.
Aug 20 2001
kaffiene wrote:"Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B80C66E.A86462DB earthlink.net... ...vector example above) then the natural precendence of operators may change as well. Peter.It seems reasonable to me that all new operators should same precedence as the dot operator. If you want to specify a different order, you need to use parenthesis. The idea here is that these operators are merely syntactic sugar for the functional notation. A :+: B === A.add(B). It is a bit easier to read. But you don't want to encourage excessive proliferation, because if you do, then it won't be easier any more. So you give them the same precedence as the dot operator. (That's what they really are.)
Aug 21 2001
"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:3B828ADA.8010506 earthlink.net...kaffiene wrote:well."Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B80C66E.A86462DB earthlink.net... ...vector example above) then the natural precendence of operators may change asI agree with your point about the profliferation of operator overloading making things harder. That's why I was arguing previously that it's probably better not to overload operators at all. Peter.Peter.It seems reasonable to me that all new operators should same precedence as the dot operator. If you want to specify a different order, you need to use parenthesis. The idea here is that these operators are merely syntactic sugar for the functional notation. A :+: B === A.add(B). It is a bit easier to read. But you don't want to encourage excessive proliferation, because if you do, then it won't be easier any more. So you give them the same precedence as the dot operator. (That's what they really are.)
Aug 21 2001
kaffiene wrote:"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:3B828ADA.8010506 earthlink.net...But you ignore the adjective "excessive". It makes a big difference here. Reasonable use of operator syntax greatly IMPROVES readability. Still, it's probably reasonable to restrict the overloading to non-predefined operators.kaffiene wrote:well."Christophe de Dinechin" <descubes earthlink.net> wrote in message news:3B80C66E.A86462DB earthlink.net... ...vector example above) then the natural precendence of operators may change asI agree with your point about the profliferation of operator overloading making things harder. That's why I was arguing previously that it's probably better not to overload operators at all. Peter.Peter.It seems reasonable to me that all new operators should same precedence as the dot operator. If you want to specify a different order, you need to use parenthesis. The idea here is that these operators are merely syntactic sugar for the functional notation. A :+: B === A.add(B). It is a bit easier to read. But you don't want to encourage excessive proliferation, because if you do, then it won't be easier any more. So you give them the same precedence as the dot operator. (That's what they really are.)
Aug 22 2001
kaffiene wrote:I said it was an impression, I never claimed it was a fact. You did not qualify your comment above as such ;-) And, sometimes, sarcasm is funny, if properly identified as such. Sorry the other guy took it personally, it was actually a grunt against the C++ committee and Bjarne's decision to have template<> rather than, e.g., template[]. I take your point and will try to avoid that in the future, but I'd like you to get back to the point and answer my questions. How is A.Add(B) not introducing maintenance complexity in complicated expressions? How is A.Add(B) not adding a new notation that differs from the traditional A+B?My impression is that your own background did not expose you to such "math-oriented" environments. Then, you are right, avoiding operator overloading is probably the right thing to do.I majored in Computer Graphics. I quite familiar with both animation for broadcast using raytracing and real time graphics using OpenGL and DirectX. I have written several raytracers. I am about to take up a job with a broadcast graphics company. These are "math-oriented" environments. Your impression is wrong. I noticed that another poster asked you to refrain from sarcasm at one point - I would also ask you to refrain from personal assumptions. If you want to debate the technical merits of a language feature, please do so but don't do it by claiming that people with alternate opinions are ignorant.??? You may be right in your field, but that's the very first time I ever hear this. Any pointer justifying this notation? Let me take a few books here. Quantum mechanics book, formula H^=E0+A'/4.sigma1.sigma2+Dsigma[1,z].sigma[2.z]. I know that the . has higher precedence here, no parentheses. An old book by Lillian Lieber on Relativity (one of the few I have in English): Tensor notation all over the place: A.B+C.D, where + is lower priority. Just in case you wonder, some of these tensor products actually are the dot product you are describing A third book, same thing, sampling three equations at random, they all had A+B.C mean A+(B.C). So, again, I'm very curious wrt. the field where A+B.C means (A+B).C. If this is a "frequent case", I might change my mind on priority of operators in LX.No, that is a very bad idea, and not only for technological reasons. Mathematicians invented operator precedence, not compilers (precedence isnotan artifact of limited technology, it is a simplifying notation.) I don'tknowof any context where mathematicians read AxB+C as meaning (Ax(B+C))... ButIf you are talking about vectors, then A + B * C is the vector A added to vector B (resulting in a vector) crossed with the vector C (resulting in a vector). This evaluates as (A + B) * C. There you have a context in which the standard arithmetic operator precedence does not hold.We have a different definition of "new" operator. You call "new" an operator that can be overloaded, I call new an operator that doesn't exist in the language. While I have a weaker feeling about defining some arbitray precedence for "A znort B", I have a strong feeling about defining it for "A*B" as a function of the types of A and B. There, compiler technology has a serious issue, because it means that to parse any expression, you have to do semantics on the items in the expression. That makes it really really hard. In addition, unless you give me a pointer for the A+B.C example above, I stick to it that mathematicians do not generally change the precedence of operators based on the type of arguments. Christophetechnology also indicates that this is a bad idea, because arbitrary precedences would render most expressions ambiguous.*sigh* - please read the history of this thread. My point is that for *new* operators that don't already exist in the language, you need to specify precedence. For example, a Vector class could overload * for cross-product, but C++ doesn't allow overloading . (period) for dot product or ||v|| for magnitude. If you introduce new operators you must be able to specify the precedence. If you change the context of an operator (e.g. * in the vector example above) then the natural precendence of operators may change as well.
Aug 22 2001
[snip]I take your point and will try to avoid that in the future, but I'd likeyou toget back to the point and answer my questions. How is A.Add(B) notintroducingmaintenance complexity in complicated expressions? How is A.Add(B) notadding anew notation that differs from the traditional A+B?My point is that you will be using <class>.<method>(<params>) anyway for 'normal' methods on the class - some people will use this for things like addition , subtraction etc... other people will use <class> + <class>, <class> * scalar etc... When you get programmers looking over the code, some classes will do things using method calls, some will do things using overloaded operators. The code is therefore more variant in style which means an increased maintenence cost. In *either* approach (overloaded operators or all method calls) you will still get the situation that a + b will be valid for all scalars and invalid for some classes (all in the case of no operator overloading). Even if you allow operator overloading, you can still have A.Add(B) as a variant notation so I reject the assertion that not having operator overloading gives you a 'new notation'.isNo, that is a very bad idea, and not only for technological reasons. Mathematicians invented operator precedence, not compilers (precedencedon'tnotan artifact of limited technology, it is a simplifying notation.) IButknowof any context where mathematicians read AxB+C as meaning (Ax(B+C))...toIf you are talking about vectors, then A + B * C is the vector A addedavector B (resulting in a vector) crossed with the vector C (resulting inwhichvector). This evaluates as (A + B) * C. There you have a context inhearthe standard arithmetic operator precedence does not hold.??? You may be right in your field, but that's the very first time I everthis. Any pointer justifying this notation? Let me take a few books here. Quantum mechanics book, formula H^=E0+A'/4.sigma1.sigma2+Dsigma[1,z].sigma[2.z]. I know that the . hashigherprecedence here, no parentheses. An old book by Lillian Lieber on Relativity (one of the few I have inEnglish):Tensor notation all over the place: A.B+C.D, where + is lower priority.Just incase you wonder, some of these tensor products actually are the dotproduct youare describing A third book, same thing, sampling three equations at random, they all had A+B.C mean A+(B.C). So, again, I'm very curious wrt. the field where A+B.C means (A+B).C. Ifthisis a "frequent case", I might change my mind on priority of operators inLX. Oh sorry - I didn't mean to imply that the + operator had a higher precedence than *, I was using the brackets to indicate how the notation is parsed naturally. The + operator - vector addition does not have a naturally higher precedence than * - vector cross product. It parses naturally left to right. [snip] Peter.
Aug 22 2001
If everyone is dead keen on operator overloading, then let's have it. But if we're going to add it, let's at least be able to add new (lexically new) operators such as A . B and ||v||. I can live with inheriting the precedence of 'standard' operators such as * - + / etc, as long as for new operators you can specificy their precedence (e.g., I'd like ||v|| to have the smae precedence as unary -) Peter. "kaffiene" <kaffiene xtra.co.nz> wrote in message news:9m17t7$19b9$1 digitaldaemon.com...[snip]invalidI take your point and will try to avoid that in the future, but I'd likeyou toget back to the point and answer my questions. How is A.Add(B) notintroducingmaintenance complexity in complicated expressions? How is A.Add(B) notadding anew notation that differs from the traditional A+B?My point is that you will be using <class>.<method>(<params>) anyway for 'normal' methods on the class - some people will use this for things like addition , subtraction etc... other people will use <class> + <class>, <class> * scalar etc... When you get programmers looking over the code, some classes will do things using method calls, some will do things using overloaded operators. The code is therefore more variant in style which means an increased maintenence cost. In *either* approach (overloaded operators or all method calls) you will still get the situation that a + b will be valid for all scalars andfor some classes (all in the case of no operator overloading). Even if you allow operator overloading, you can still have A.Add(B) as a variant notation so I reject the assertion that not having operator overloading gives you a 'new notation'.(precedenceNo, that is a very bad idea, and not only for technological reasons. Mathematicians invented operator precedence, not compilersis(Ax(B+C))...don'tnotan artifact of limited technology, it is a simplifying notation.) Iknowof any context where mathematicians read AxB+C as meaningButintoIf you are talking about vectors, then A + B * C is the vector A addedvector B (resulting in a vector) crossed with the vector C (resultingaeverwhichvector). This evaluates as (A + B) * C. There you have a context inthe standard arithmetic operator precedence does not hold.??? You may be right in your field, but that's the very first time Ihearhadthis. Any pointer justifying this notation? Let me take a few books here. Quantum mechanics book, formula H^=E0+A'/4.sigma1.sigma2+Dsigma[1,z].sigma[2.z]. I know that the . hashigherprecedence here, no parentheses. An old book by Lillian Lieber on Relativity (one of the few I have inEnglish):Tensor notation all over the place: A.B+C.D, where + is lower priority.Just incase you wonder, some of these tensor products actually are the dotproduct youare describing A third book, same thing, sampling three equations at random, they allisA+B.C mean A+(B.C). So, again, I'm very curious wrt. the field where A+B.C means (A+B).C. Ifthisis a "frequent case", I might change my mind on priority of operators inLX. Oh sorry - I didn't mean to imply that the + operator had a higher precedence than *, I was using the brackets to indicate how the notationparsed naturally. The + operator - vector addition does not have a naturally higher precedence than * - vector cross product. It parses naturally left to right. [snip] Peter.
Aug 22 2001
kaffiene wrote:If everyone is dead keen on operator overloading, then let's have it. But if we're going to add it, let's at least be able to add new (lexically new) operators such as A . B and ||v||. I can live with inheriting the precedence of 'standard' operators such as * - + / etc, as long as for new operators you can specificy their precedence (e.g., I'd like ||v|| to have the smae precedence as unary -)Agreed, with support for operators written with arbitrary Unicode. (Arrggh. I'm crushed. The bastards rejected the Klingon encoding for Unicode. There is no justice in the world.) -RB
Aug 22 2001
ButIf everyone is dead keen on operator overloading, then let's have it.new)if we're going to add it, let's at least be able to add new (lexicallynewoperators such as A . B and ||v||. I can live with inheriting the precedence of 'standard' operators such as * - + / etc, as long as forhaveoperators you can specificy their precedence (e.g., I'd like ||v|| toUnicode.the smae precedence as unary -)Agreed, with support for operators written with arbitrary Unicode. (Arrggh. I'm crushed. The bastards rejected the Klingon encoding forThere is no justice in the world.):-) hehe
Aug 22 2001
Hmph, it's really hard to decide where exactly to put a post when you're replying to many... So, I was thinking about operator overloading and templates a fair bit last night. You see, I like both of them, though not enough to defend them with the zeal that some have. Although I use them, I'd be willing to lose them, but I would mourn their demise. While I was so thinking, I came up with an idea that had been described previously, but I don't think ever fully and in one place. My train of thought went as such: One of the main complaints about operator overloading is it confuses what a given operator means in a given situation. This is a Bad Thing. However, we get around this by not using operator overloading, but operator definition. Thus I refer to exhibit a), by Charles Hixson:Perhaps one should instead be able to define infix functions (i.e., operators) have a form like, O, just as colons, no control characters, no parens, bracketts, or braces, nobackslash, and surrounded by colons. Also require white-space separation from everything else. So one could define :+: to add matrices, etc., and as these would really be functions, they should follow the normal overloading rules of functions. Don't do operator *overloading* do operator *definition*! So, having come up with a completely unoriginal idea, I got excited. But :+: and :-: and :*: and such all over the place could get quite ugly, IMHO. So how to solve this? Enter exhibits b) and c), by Rusell Bornschlegel:Agreed, with support for operators written with arbitrary Unicode.This would let you use, e.g., u22C5 ("dot operator") for matrix multiply, u22C5 and u00D7 ("multiplication sign") for dot and cross products of vectors, u221A, u221B, u221C for square, third, and fourth roots, etc.Unicode! D supports Unicode! Again excited that I had found somthing completely unoriginal, I rushed to my computer, and went to www.unicode.org. I'm not an expert on Unicode, but I know what it does. I thought to myself: "Unicode is perfect! It must have an entire section devoted to mathematical symbols!" And lo-and-behold! It does! For the interested, you can look here: http://www.unicode.org/charts/PDF/U2200.pdf (PDF) or here: http://charts.unicode.org/Web/U2200.html (GIFs, but I couldn't connect) If you haven't seen the vast extent of possibilities with this block, go check out that PDF file. Neato. So, the end result of my proposition is this: Allow the definition of new infix and unary operators from the Unicode block 2200 to 22FF, mathematical operators. Also, symbols from this block are *reserved* for new operators. (The allowance of colon delimeted operators was something I hadn't thought of... but could be another allowed grammar for new ops) The reason I don't say 'arbitrary' unicode is that then I'd go right ahead and define all sorts of cool operators from the Japanese kanji. Obfuscated D at its finest. Heck, I'd see if I could make Rashoomon with a few english interjections a program :) I think this takes care of some of the concerns about operator overloading/definition. I'm going to do a point-by-point on Angus Graham's wonderful list, which outlines just about every reason not to have operators change (and which I 100% agree with, despite liking operator overloading). However, I'm going to rearrange it into "solved" and "not-solved": Solved (or minimised) ---------------------- I don't like not being able to see at a glance what is a built intype andwhat is a class. Stroustrup thinks classes should not be second class citizens. I disagree.Problem solved. New operators for new types.- I don't look forward to explaining their use to new programmers.True, but I think that is minimised by the fact that you're adding, not redefining.- I don't like the way overloaded operators hide their true runtimecost ina cursory look at the code.The cost would be less hidden due to the fact that they are unique, and therefore identifiable.- I don't like the way they reduce the self-documenting nature of code. concatenate() is clear,convert_strings_to_integer_representations_and_add_them_and_then_convert_result_to_string() is clear, but string_result = string1 + string2 is definitely not clear.Less of a problem due to the uniqueness of the operators. Not solved ----------- I don't like the added complexity to the language.If you mean, just as a feature... well, I can't stop that :)- I don't like the way overloaded operators can be easily writtenwrong andused wrong so that they generate various temporaries and assignments that are not obvious to the programmer.*sigh* I can't argue against this point, it's too true.- I don't like the way they are harder to debug, as they encourageputtingmany function calls on one line.Again, a problem.- I don't like the way we always end up with some classes usingoverloadedoperators and some not leading to two ways of doing the same thing.Yet again, a fundamental problem. So, I'll admit it isn't perfect, but it might be a start for a compromise between the two camps. OTOH, to be honest, I wouldn't miss them much at all... for mathematical vectors, and that's about it. But, in what appears to be the "philosophy of D" I was looking for the "better solution". Yet another treatise from the guy who talks too much. Cheers, Eric P.S. I never did find a solution for templates, and I'd miss them a lot... *sigh* P.P.S. For me, generics won't cut it. I need meta-programming... P.P.P.S. Would you like them in a house? Would you like them with a mouse? Or in a box? Or with a fox? Would you like them with a goat? Would you like them on a boat? (I'm sorry, I love the great Doctor... not to mention I think operator overloading is much more acceptable with a goat)
Aug 26 2001
Thanks for the entertaining and excellent summary. BTW, what is "meta-programming" as opposed to generics? Eric Gerlach wrote in message <3B892085.2060903 canada.com>...Hmph, it's really hard to decide where exactly to put a post when you're replying to many... So, I was thinking about operator overloading and templates a fair bit last night. You see, I like both of them, though not enough to defend them with the zeal that some have. Although I use them, I'd be willing to lose them, but I would mourn their demise. While I was so thinking, I came up with an idea that had been described previously, but I don't think ever fully and in one place. My train of thought went as such: One of the main complaints about operator overloading is it confuses what a given operator means in a given situation. This is a Bad Thing. However, we get around this by not using operator overloading, but operator definition. Thus I refer to exhibit a), by Charles Hixson:sPerhaps one should instead be able to define infix functions (i.e., operators) have a form like, O, just as colons, no control characters, no parens, bracketts, or braces, nobackslash, and surrounded by colons. Also require white-space separation from everything else. So one could define :+: to add matrices, etc., and as these would really be functions, they should follow the normal overloading rules of functions. Don't do operator *overloading* do operator *definition*! So, having come up with a completely unoriginal idea, I got excited. But :+: and :-: and :*: and such all over the place could get quite ugly, IMHO. So how to solve this? Enter exhibits b) and c), by Rusell Bornschlegel:Agreed, with support for operators written with arbitrary Unicode.This would let you use, e.g., u22C5 ("dot operator") for matrix multiply, u22C5 and u00D7 ("multiplication sign") for dot and cross products of vectors, u221A, u221B, u221C for square, third, and fourth roots, etc.Unicode! D supports Unicode! Again excited that I had found somthing completely unoriginal, I rushed to my computer, and went to www.unicode.org. I'm not an expert on Unicode, but I know what it does. I thought to myself: "Unicode is perfect! It must have an entire section devoted to mathematical symbols!" And lo-and-behold! It does! For the interested, you can look here: http://www.unicode.org/charts/PDF/U2200.pdf (PDF) or here: http://charts.unicode.org/Web/U2200.html (GIFs, but I couldn't connect) If you haven't seen the vast extent of possibilities with this block, go check out that PDF file. Neato. So, the end result of my proposition is this: Allow the definition of new infix and unary operators from the Unicode block 2200 to 22FF, mathematical operators. Also, symbols from this block are *reserved* for new operators. (The allowance of colon delimeted operators was something I hadn't thought of... but could be another allowed grammar for new ops) The reason I don't say 'arbitrary' unicode is that then I'd go right ahead and define all sorts of cool operators from the Japanese kanji. Obfuscated D at its finest. Heck, I'd see if I could make Rashoomon with a few english interjections a program :) I think this takes care of some of the concerns about operator overloading/definition. I'm going to do a point-by-point on Angus Graham's wonderful list, which outlines just about every reason not to have operators change (and which I 100% agree with, despite liking operator overloading). However, I'm going to rearrange it into "solved" and "not-solved": Solved (or minimised) ---------------------- I don't like not being able to see at a glance what is a built intype andwhat is a class. Stroustrup thinks classes should not be second class citizens. I disagree.Problem solved. New operators for new types.- I don't look forward to explaining their use to new programmers.True, but I think that is minimised by the fact that you're adding, not redefining.- I don't like the way overloaded operators hide their true runtimecost ina cursory look at the code.The cost would be less hidden due to the fact that they are unique, and therefore identifiable.- I don't like the way they reduce the self-documenting nature of code. concatenate() is clear,convert_strings_to_integer_representations_and_add_them_and_then_convert_rethatult_to_string() is clear, but string_result = string1 + string2 is definitely not clear.Less of a problem due to the uniqueness of the operators. Not solved ----------- I don't like the added complexity to the language.If you mean, just as a feature... well, I can't stop that :)- I don't like the way overloaded operators can be easily writtenwrong andused wrong so that they generate various temporaries and assignmentsare not obvious to the programmer.*sigh* I can't argue against this point, it's too true.- I don't like the way they are harder to debug, as they encourageputtingmany function calls on one line.Again, a problem.- I don't like the way we always end up with some classes usingoverloadedoperators and some not leading to two ways of doing the same thing.Yet again, a fundamental problem. So, I'll admit it isn't perfect, but it might be a start for a compromise between the two camps. OTOH, to be honest, I wouldn't miss them much at all... for mathematical vectors, and that's about it. But, in what appears to be the "philosophy of D" I was looking for the "better solution". Yet another treatise from the guy who talks too much. Cheers, Eric P.S. I never did find a solution for templates, and I'd miss them a lot... *sigh* P.P.S. For me, generics won't cut it. I need meta-programming... P.P.P.S. Would you like them in a house? Would you like them with a mouse? Or in a box? Or with a fox? Would you like them with a goat? Would you like them on a boat? (I'm sorry, I love the great Doctor... not to mention I think operator overloading is much more acceptable with a goat)
Aug 26 2001
Thanks for the entertaining and excellent summary. BTW, what is "meta-programming" as opposed to generics?It sounds like you are entreating me to treat you with another treatise. Hopefully I'll be able to keep the length of this down... though on a topic so near and dear to my heart, I sincerely doubt it. :) Meta-programming... meta-proramming... where to start. Well, in a nutshell it's a way to write a program that is run at compile-time by the compiler, of which the output is code, which is then compiled. Hmmm.... that probably makes little sense. Allow me to illustrate with an example in C++: The factorial. template <int N> class Factorial { public: enum { val = N*Factorial<N-1>::value }; } tmeplate <1> class Factorial { public: enum { value = 1; } } void main() { int i = Factorial<5>::value; } So what is going on here? Well, when the 'Factorial<5>::value' is compiled, the compiler tries to resolve it. But it can't without computing Factorial<4>::value, and so on down the recursion. Then the compiler computes the result of the expression (because it has to be constant, it's an enum), and uses it *as a constant* in the program. You get the time savings of not having to compute it at runtime. Now, I'll admit that was a pretty useless example. It makes for somewhat more readable code, but otherwise isn't great. Where template metaprogramming can really be useful is in things like Matricies. Now hold on, and I'll see if I can get this right first shot. template <int I, int J, int N> static class MatrixComp { static void add(const Matrix<N> & m1, const Matrix<N> & m2, Matrix<N> & result) { result.m[I][J] = m1.m[I][J] + m2.m[I][J]; MatrixComp<I-1,J,N>::add(m1, m2, result); } } template <0, int J, int N> static class MatrixComp { static void add(const Matrix<N> & m1, const Matrix<N> & m2, Matrix<N> & result) { result.m[0][J] = m1.m[0][J] + m2.m[0][J]; MatrixComp<N-1,J-1,N>::add(m1, m2, result); } } template <0, 0, int N> static class MatrixComp { static void add(const Matrix<N> & m1, const Matrix<N> & m2, Matrix<N> & result) { result.m[0][0] = m1.m[0][0] + m2.m[0][0]; } } template <int N> class Matrix { public: float m[N][N]; void add(const Matrix<N> & m) { Matrix<N> temp; MatrixComp<N-1,N-1,N>::add(*this, m, temp); this->m = temp.m; // assuming this was legal :) } } void main() { Matrix<3> m1, m2; /* fill matricies */ m1.add(m2); } So, what does all that jibber-jabber do for you? Well, the add() call in main gets expanded at compile time to this: add(m2) { Matrix<3> temp; temp.m[2][2] = (*this).m[2][2] + m2[2][2]; temp.m[2][1] = (*this).m[2][1] + m2[2][1]; temp.m[2][0] = (*this).m[2][0] + m2[2][0]; temp.m[1][2] = (*this).m[1][2] + m2[1][2]; temp.m[1][1] = (*this).m[1][1] + m2[1][1]; temp.m[1][0] = (*this).m[1][0] + m2[1][0]; temp.m[0][2] = (*this).m[0][2] + m2[0][2]; temp.m[0][1] = (*this).m[0][1] + m2[0][1]; temp.m[0][0] = (*this).m[0][0] + m2[0][0]; this->m = temp.m; } And voila! All this done *before* the code is even compiled! Incredible! Now, I can hear some people saying: "But the optimiser will handle all that for you!" But that isn't completely true. First of all, you've just given the compiler a head-start. It might be able to squeeze additional optimisations out because you've already unraveled the loops. Second, consider matrix multiplication, which requires several nested loops. Written properly using template meta-programming, *all* of those loops are unraveled at compile-time, and you get a straight function such as the one above, which consists solely of multiplications and additions. No loops, no counters, just wonderfully optimised code. Of course, the more complex the procedure, the greater the runtime savings. However, this comes at increased compile-time cost. Doing template meta-programming takes a lot of time to compile, as the compiler is acting as an interpreter... in fact, it's acting very similar to LISP. Also, this generates much larger code files. But if you need the speed it can be well worth the trouble. I think that's a decent intro to the topic. I only found out about it recently myself. But it was love at first sight. Truly, properly done metaprogramming is a thing of beauty. My advantage was that I learned it from someone who learned it from the guy who wrote the book on template metaprogramming, Todd Veldhuizen. You can find his page on the subject here: http://www.extreme.indiana.edu/~tveldhui/papers/Template-Metaprograms/meta-art.html If you want to see a good metaprogramming library, check out blitz++, I've never used it myself, but apparantly it's quite good at what it does. Anywho, that's it for me for now. I don't know if stuff like this could ever make it into D (and in fact Walter has stated D isn't for real-time, so this doesn't fit the schema anyways), but it's neat stuff anyways. Eric P.S. An interesting tidbit: I wrote a template metaprogrammed matrix inversion routine. It's got 3-5 levels of recursion... I'd have to count them again. GCC, in attempting to compile and optimise a 6x6 matrix with this inversion routine, ate up >600MB of RAM. It crashed before it finished. Fortunately, we only have to use 4x4 matricies in our code.
Aug 27 2001
Ok, I see. Thanks for the explanation. I'm not sure I'm ready to try it yet, though! Eric Gerlach wrote in message <3B8B0F5E.7030305 canada.com>...art.htmlThanks for the entertaining and excellent summary. BTW, what is "meta-programming" as opposed to generics?It sounds like you are entreating me to treat you with another treatise. Hopefully I'll be able to keep the length of this down... though on a topic so near and dear to my heart, I sincerely doubt it. :) Meta-programming... meta-proramming... where to start. Well, in a nutshell it's a way to write a program that is run at compile-time by the compiler, of which the output is code, which is then compiled. Hmmm.... that probably makes little sense. Allow me to illustrate with an example in C++: The factorial. template <int N> class Factorial { public: enum { val = N*Factorial<N-1>::value }; } tmeplate <1> class Factorial { public: enum { value = 1; } } void main() { int i = Factorial<5>::value; } So what is going on here? Well, when the 'Factorial<5>::value' is compiled, the compiler tries to resolve it. But it can't without computing Factorial<4>::value, and so on down the recursion. Then the compiler computes the result of the expression (because it has to be constant, it's an enum), and uses it *as a constant* in the program. You get the time savings of not having to compute it at runtime. Now, I'll admit that was a pretty useless example. It makes for somewhat more readable code, but otherwise isn't great. Where template metaprogramming can really be useful is in things like Matricies. Now hold on, and I'll see if I can get this right first shot. template <int I, int J, int N> static class MatrixComp { static void add(const Matrix<N> & m1, const Matrix<N> & m2, Matrix<N> & result) { result.m[I][J] = m1.m[I][J] + m2.m[I][J]; MatrixComp<I-1,J,N>::add(m1, m2, result); } } template <0, int J, int N> static class MatrixComp { static void add(const Matrix<N> & m1, const Matrix<N> & m2, Matrix<N> & result) { result.m[0][J] = m1.m[0][J] + m2.m[0][J]; MatrixComp<N-1,J-1,N>::add(m1, m2, result); } } template <0, 0, int N> static class MatrixComp { static void add(const Matrix<N> & m1, const Matrix<N> & m2, Matrix<N> & result) { result.m[0][0] = m1.m[0][0] + m2.m[0][0]; } } template <int N> class Matrix { public: float m[N][N]; void add(const Matrix<N> & m) { Matrix<N> temp; MatrixComp<N-1,N-1,N>::add(*this, m, temp); this->m = temp.m; // assuming this was legal :) } } void main() { Matrix<3> m1, m2; /* fill matricies */ m1.add(m2); } So, what does all that jibber-jabber do for you? Well, the add() call in main gets expanded at compile time to this: add(m2) { Matrix<3> temp; temp.m[2][2] = (*this).m[2][2] + m2[2][2]; temp.m[2][1] = (*this).m[2][1] + m2[2][1]; temp.m[2][0] = (*this).m[2][0] + m2[2][0]; temp.m[1][2] = (*this).m[1][2] + m2[1][2]; temp.m[1][1] = (*this).m[1][1] + m2[1][1]; temp.m[1][0] = (*this).m[1][0] + m2[1][0]; temp.m[0][2] = (*this).m[0][2] + m2[0][2]; temp.m[0][1] = (*this).m[0][1] + m2[0][1]; temp.m[0][0] = (*this).m[0][0] + m2[0][0]; this->m = temp.m; } And voila! All this done *before* the code is even compiled! Incredible! Now, I can hear some people saying: "But the optimiser will handle all that for you!" But that isn't completely true. First of all, you've just given the compiler a head-start. It might be able to squeeze additional optimisations out because you've already unraveled the loops. Second, consider matrix multiplication, which requires several nested loops. Written properly using template meta-programming, *all* of those loops are unraveled at compile-time, and you get a straight function such as the one above, which consists solely of multiplications and additions. No loops, no counters, just wonderfully optimised code. Of course, the more complex the procedure, the greater the runtime savings. However, this comes at increased compile-time cost. Doing template meta-programming takes a lot of time to compile, as the compiler is acting as an interpreter... in fact, it's acting very similar to LISP. Also, this generates much larger code files. But if you need the speed it can be well worth the trouble. I think that's a decent intro to the topic. I only found out about it recently myself. But it was love at first sight. Truly, properly done metaprogramming is a thing of beauty. My advantage was that I learned it from someone who learned it from the guy who wrote the book on template metaprogramming, Todd Veldhuizen. You can find his page on the subject here: http://www.extreme.indiana.edu/~tveldhui/papers/Template-Metaprograms/meta-If you want to see a good metaprogramming library, check out blitz++, I've never used it myself, but apparantly it's quite good at what it does. Anywho, that's it for me for now. I don't know if stuff like this could ever make it into D (and in fact Walter has stated D isn't for real-time, so this doesn't fit the schema anyways), but it's neat stuff anyways. Eric P.S. An interesting tidbit: I wrote a template metaprogrammed matrix inversion routine. It's got 3-5 levels of recursion... I'd have to count them again. GCC, in attempting to compile and optimise a 6x6 matrix with this inversion routine, ate up >600MB of RAM. It crashed before it finished. Fortunately, we only have to use 4x4 matricies in our code.
Aug 29 2001
This is going to look like I'm jumping the fence repeatedly on operator overloading. For the record, I'm in favor of D incorporating C++'s operator overloading capability (though not necessarily using the same definition syntax) _and_ in extending this to arbitrary single-unicode-above-ASCII-character operators. I understand the problems with operator overloading, and am willing to accept them. My need to write code manipulating matrices and vectors makes this an absolute requirement for my language-of-choice. Eric Gerlach wrote:So, the end result of my proposition is this: Allow the definition of new infix and unary operators from the Unicode block 2200 to 22FF, mathematical operators. Also, symbols from this block are *reserved* for new operators. (The allowance of colon delimeted operators was something I hadn't thought of... but could be another allowed grammar for new ops) The reason I don't say 'arbitrary' unicode is that then I'd go right ahead and define all sorts of cool operators from the Japanese kanji. Obfuscated D at its finest. Heck, I'd see if I could make Rashoomon with a few english interjections a program :)I'd be annoyed if Unicode operator definition were adopted with that arbitrary restriction, personally. The Miscellaneous Technicals in the 2300 block include the operators used by the APL language, which at least have some justification for being used as user-defined operators in a programming language. The Mathematical Operators in the 2200 block also include a slash, an asterisk, and a tilde, so you can't easily distinguish from the builtin operators. There are lots of operators there that look something like other operators in C. Your proposal is thus simultaneously too restrictive for me, and not safe enough for Mr. Graham. -RB
Aug 26 2001
For the record, I'm in favor of D incorporating C++'s operator overloading capability (though not necessarily using the same definition syntax) _and_ in extending this to arbitrary single-unicode-above-ASCII-character operators.I'm not too picky about operator overload being in or not (I was just proposing a solution) but arbitrary unicode operators is a no-no. A big no-no. Have you ween how many characters there are in unicode? It's crazy to allow all those for operators. Go look here: http://www.unicode.org/charts/PDF/U4E00.pdf There are 0x9FAF - 0x4E00 == 0x51AF == 20911 symbols in that section of unicode alone. I don't want a single one of them being an operator! The main reason behind that is some people read those as words, and would be very confused. If that isn't enough, there are dozens of other scrips that could be redefined as operators with a generic unicode solution. If it exists, it should be relegated to the block of symbols *called* Mathematical Operators.
Aug 27 2001
Eric Gerlach wrote:There are 0x9FAF - 0x4E00 == 0x51AF == 20911 symbols in that section of unicode alone. I don't want a single one of them being an operator! The main reason behind that is some people read those as words, and would be very confused.But as I point out, that arbitrary restriction doesn't make it particularly hard to confuse people. The ability to overload the mathematical-operator-asterisk to mean something different from the ASCII asterisk is far more likely to be abused than, say, something in arabic script.
Sep 05 2001
Russell Borogove wrote:Eric Gerlach wrote:You can also confuse people by naming a routine that takes the RMS of two numbers add. The idea is to not confuse them by accident. The possibility of obfuscation is always with us.There are 0x9FAF - 0x4E00 == 0x51AF == 20911 symbols in that section of unicode alone. I don't want a single one of them being an operator! The main reason behind that is some people read those as words, and would be very confused.But as I point out, that arbitrary restriction doesn't make it particularly hard to confuse people. The ability to overload the mathematical-operator-asterisk to mean something different from the ASCII asterisk is far more likely to be abused than, say, something in arabic script.
Sep 06 2001
Eric Gerlach wrote:... Unicode! D supports Unicode! Again excited that I had found somthing completely unoriginal, I rushed to my computer, and went to www.unicode.org. I'm not an expert on Unicode, but I know what it does. I thought to myself: "Unicode is perfect! It must have an entire section devoted to mathematical symbols!" And lo-and-behold! It does! For the interested, you can look here: http://www.unicode.org/charts/PDF/U2200.pdf (PDF) or here: http://charts.unicode.org/Web/U2200.html (GIFs, but I couldn't connect) If you haven't seen the vast extent of possibilities with this block, go check out that PDF file. Neato. So, the end result of my proposition is this: Allow the definition of new infix and unary operators from the Unicode block 2200 to 22FF, mathematical operators. Also, symbols from this block are *reserved* for new operators. (The allowance of colon delimeted operators was something I hadn't thought of... but could be another allowed grammar for new ops) ...I prefer symbols that are easier to type on a standard keyboard, but I do find your suggestion acceptable. It would have the side effect (benefit?) of making the symbols harder to enter, and thus less commonly used. But I feel that it might be carying things a bit to extremes, unless there is some obviously easy way to remember how to enter them.
Aug 27 2001
I prefer symbols that are easier to type on a standard keyboard, but I do find your suggestion acceptable. It would have the side effect (benefit?) of making the symbols harder to enter, and thus less commonly used. But I feel that it might be carying things a bit to extremes, unless there is some obviously easy way to remember how to enter them.Yes, that was the downside to the whole idea... not many people have unicode-enabled text editors... but maybe this would encourage proliferation of them! :)
Aug 27 2001
"kaffiene" <kaffiene xtra.co.nz> wroteIf everyone is dead keen on operator overloading, then let's have it.Not everyone is dead keen on it. I haven't commented on the subject (or followed this thread) simply because I'm so uninterested in it. But so that my silence != consent, I will say what I don't like about overloaded operators (although I'm sure I will repeat some stuff). - I don't like not being able to see at a glance what is a built in type and what is a class. Stroustrup thinks classes should not be second class citizens. I disagree. - I don't like the added complexity to the language. - I don't look forward to explaining their use to new programmers. - I don't like the way overloaded operators can be easily written wrong and used wrong so that they generate various temporaries and assignments that are not obvious to the programmer. - I don't like the way overloaded operators hide their true runtime cost in a cursory look at the code. - I don't like the way they are harder to debug, as they encourage putting many function calls on one line. - I don't like the way they reduce the self-documenting nature of code. concatenate() is clear, convert_strings_to_integer_representations_and_add_them_and_then_convert_res ult_to_string() is clear, but string_result = string1 + string2 is definitely not clear. - I don't like the way we always end up with some classes using overloaded operators and some not leading to two ways of doing the same thing. Angus Graham ps - I do not like them on a train. - I do not like them on a plane. - I do not like them here nor there. - I do not like them anywhere.
Aug 22 2001
Same here, I don't like operator overloads, the complexity added for 'syntactic' sugar is not worth it. I use to write C++ libraries with operator overloads, and there are so many gotchas. If someone wants those, there's always C++. --Kent
Aug 22 2001
hehe - I don't like operator overloading either, but given that everyone was beating me up about it, I assumed I was in the minority. I agree with everything on your list. Peter. "Angus Graham" <agraham_d agraham.ca> wrote in message news:9m1epf$1d47$1 digitaldaemon.com..."kaffiene" <kaffiene xtra.co.nz> wroteandIf everyone is dead keen on operator overloading, then let's have it.Not everyone is dead keen on it. I haven't commented on the subject (or followed this thread) simply because I'm so uninterested in it. But so that my silence != consent, I will say what I don't like about overloaded operators (although I'm sure I will repeat some stuff). - I don't like not being able to see at a glance what is a built in typewhat is a class. Stroustrup thinks classes should not be second class citizens. I disagree. - I don't like the added complexity to the language. - I don't look forward to explaining their use to new programmers. - I don't like the way overloaded operators can be easily written wrongandused wrong so that they generate various temporaries and assignments that are not obvious to the programmer. - I don't like the way overloaded operators hide their true runtime costina cursory look at the code. - I don't like the way they are harder to debug, as they encourage putting many function calls on one line. - I don't like the way they reduce the self-documenting nature of code. concatenate() is clear,convert_strings_to_integer_representations_and_add_them_and_then_convert_result_to_string() is clear, but string_result = string1 + string2 is definitely not clear. - I don't like the way we always end up with some classes using overloaded operators and some not leading to two ways of doing the same thing. Angus Graham ps - I do not like them on a train. - I do not like them on a plane. - I do not like them here nor there. - I do not like them anywhere.
Aug 22 2001
Angus Graham wrote:"kaffiene" <kaffiene xtra.co.nz> wrote - I don't like not being able to see at a glance what is a built in type and what is a classSo do I.. - I don't like the way they reduce the self-documenting nature of code. concatenate() is clear, convert_strings_to_integer_representations_and_add_them_and_then_convert_res ult_to_string() is clear, but string_result = string1 + string2 is definitely not clear.I Agree. Using (member) functions with a clear self explaining name as Add, Minus, Eq, Ge, Gt, Le, etc is more self explaining as anything else IMHO.Angus Graham ps - I do not like them on a train. - I do not like them on a plane. - I do not like them here nor there. - I do not like them anywhere.<g> Arjan
Aug 23 2001
Mind if I put that in the FAQ? -Walter Angus Graham wrote in message <9m1epf$1d47$1 digitaldaemon.com>..."kaffiene" <kaffiene xtra.co.nz> wroteandIf everyone is dead keen on operator overloading, then let's have it.Not everyone is dead keen on it. I haven't commented on the subject (or followed this thread) simply because I'm so uninterested in it. But so that my silence != consent, I will say what I don't like about overloaded operators (although I'm sure I will repeat some stuff). - I don't like not being able to see at a glance what is a built in typewhat is a class. Stroustrup thinks classes should not be second class citizens. I disagree. - I don't like the added complexity to the language. - I don't look forward to explaining their use to new programmers. - I don't like the way overloaded operators can be easily written wrong and used wrong so that they generate various temporaries and assignments that are not obvious to the programmer. - I don't like the way overloaded operators hide their true runtime cost in a cursory look at the code. - I don't like the way they are harder to debug, as they encourage putting many function calls on one line. - I don't like the way they reduce the self-documenting nature of code. concatenate() is clear, convert_strings_to_integer_representations_and_add_them_and_then_convert_result_to_string() is clear, but string_result = string1 + string2 is definitely not clear. - I don't like the way we always end up with some classes using overloaded operators and some not leading to two ways of doing the same thing. Angus Graham ps - I do not like them on a train. - I do not like them on a plane. - I do not like them here nor there. - I do not like them anywhere.
Aug 23 2001
It seemed like you were mostly against A + B and Add(A, B) being synonyms, right? (OK you said A.add(B), but I hate that syntax and C++ supported the other so I used it.) Anyhow, what would you think of a syntax that allowed the design of an API to decide with a routine would be only an infix or if there could be a public function syntax too? We don't need to use C++ syntax. It was pretty ugly. If anything, it sound like Walter wants D to be an apology for what C++ did to C. I only want the operators because I doubt that we can anticipate all the good ways people use operators when they can. If we are sure we can cover it all, then fine, otherwise I'd hate to lose a good tool just because somebody else abused it. I'm not dead set on passing out guns and rope for the inexperience to shoot and hang themselves with, but the inexperienced can injure themselves with some of the most handy and powerful of tools. It might be it a good idea to leave operator overloading the the advanced or special purpose chapter of the manual and let the programmer grow into it, kind of like word alignment, inline assembler and alternate calling conventions. Dan kaffiene wrote:If everyone is dead keen on operator overloading, then let's have it. But if we're going to add it, let's at least be able to add new (lexically new) operators such as A . B and ||v||. I can live with inheriting the precedence of 'standard' operators such as * - + / etc, as long as for new operators you can specificy their precedence (e.g., I'd like ||v|| to have the smae precedence as unary -) Peter. "kaffiene" <kaffiene xtra.co.nz> wrote in message news:9m17t7$19b9$1 digitaldaemon.com...[snip]invalidI take your point and will try to avoid that in the future, but I'd likeyou toget back to the point and answer my questions. How is A.Add(B) notintroducingmaintenance complexity in complicated expressions? How is A.Add(B) notadding anew notation that differs from the traditional A+B?My point is that you will be using <class>.<method>(<params>) anyway for 'normal' methods on the class - some people will use this for things like addition , subtraction etc... other people will use <class> + <class>, <class> * scalar etc... When you get programmers looking over the code, some classes will do things using method calls, some will do things using overloaded operators. The code is therefore more variant in style which means an increased maintenence cost. In *either* approach (overloaded operators or all method calls) you will still get the situation that a + b will be valid for all scalars andfor some classes (all in the case of no operator overloading). Even if you allow operator overloading, you can still have A.Add(B) as a variant notation so I reject the assertion that not having operator overloading gives you a 'new notation'.(precedenceNo, that is a very bad idea, and not only for technological reasons. Mathematicians invented operator precedence, not compilersis(Ax(B+C))...don'tnotan artifact of limited technology, it is a simplifying notation.) Iknowof any context where mathematicians read AxB+C as meaningButintoIf you are talking about vectors, then A + B * C is the vector A addedvector B (resulting in a vector) crossed with the vector C (resultingaeverwhichvector). This evaluates as (A + B) * C. There you have a context inthe standard arithmetic operator precedence does not hold.??? You may be right in your field, but that's the very first time Ihearhadthis. Any pointer justifying this notation? Let me take a few books here. Quantum mechanics book, formula H^=E0+A'/4.sigma1.sigma2+Dsigma[1,z].sigma[2.z]. I know that the . hashigherprecedence here, no parentheses. An old book by Lillian Lieber on Relativity (one of the few I have inEnglish):Tensor notation all over the place: A.B+C.D, where + is lower priority.Just incase you wonder, some of these tensor products actually are the dotproduct youare describing A third book, same thing, sampling three equations at random, they allisA+B.C mean A+(B.C). So, again, I'm very curious wrt. the field where A+B.C means (A+B).C. Ifthisis a "frequent case", I might change my mind on priority of operators inLX. Oh sorry - I didn't mean to imply that the + operator had a higher precedence than *, I was using the brackets to indicate how the notationparsed naturally. The + operator - vector addition does not have a naturally higher precedence than * - vector cross product. It parses naturally left to right. [snip] Peter.
Aug 23 2001
Dan Hursh wrote:It seemed like you were mostly against A + B and Add(A, B) being synonyms, right? (OK you said A.add(B), but I hate that syntax and C++ supported the other so I used it.) Anyhow, what would you think of a syntax that allowed the design of an API to decide with a routine would be only an infix or if there could be a public function syntax too? We don't need to use C++ syntax. It was pretty ugly.... Dan ...But you can certainly do it the way you are talking about. Add (A, B) always works (inside of a class) if Add is a method of the class. So just make it a method of Object (or some descendant of Object that all of your classes descend from). Or put it in an interface that you implement, but far enough up the tree that it will be an ancestor to all the classes in which you are working.
Aug 24 2001
(b) Go the whole hog and design a system that allows creation of arbitrary operators and overloading the precedence of these and existant operators. This actually *would* allow your system to live up to the rhetoric, butyouhave to put up with the proliferation of style choices made by each individual programmer you work with, and live with the fact that that a maintenance programmer who is unfamiliar with the given mathematical notation will have an uphill battle to be able to work on your codebase.I think it's funny that you believe that somebody that "is unfamiliar with the given mathematical notation" would be able to understand the concepts involved in such a codebase enough to *qualify* as a maintenance programmer. I know this firsthand... I never took Calculus, so reading research papers which deal with mathematical subject matter (as I have many occasion to do as a 3D graphics programmer) usually means I'm left not fully grokking the theory behind why something works, just because they're using notation to do the explanation... notation I never learned properly. Yes, to the inexperienced, it looks like job security. Forcing mathematical concepts to be handled thru functional notation just results in really unreadably messy math, and if your *math* is unreadable, you are bound to have bugs in the math code. Let's see that maintenance programmer try to fix some of those. Sean
Oct 29 2001
While operator overloading is an idea with many merits, I just don't see that arbitrary operators with arbitrary precedence would lead to something that wouldn't be better done with YACC. "Sean L. Palmer" <spalmer iname.com> wrote in message news:9rj5av$2qnl$1 digitaldaemon.com...arbitrary(b) Go the whole hog and design a system that allows creation ofoperators.operators and overloading the precedence of these and existantprogrammer.This actually *would* allow your system to live up to the rhetoric, butyouhave to put up with the proliferation of style choices made by each individual programmer you work with, and live with the fact that that a maintenance programmer who is unfamiliar with the given mathematical notation will have an uphill battle to be able to work on your codebase.I think it's funny that you believe that somebody that "is unfamiliar with the given mathematical notation" would be able to understand the concepts involved in such a codebase enough to *qualify* as a maintenanceI know this firsthand... I never took Calculus, so reading research papers which deal with mathematical subject matter (as I have many occasion to do as a 3D graphics programmer) usually means I'm left not fully grokking the theory behind why something works, just because they're using notation todothe explanation... notation I never learned properly. Yes, to the inexperienced, it looks like job security. Forcingmathematicalconcepts to be handled thru functional notation just results in really unreadably messy math, and if your *math* is unreadable, you are bound to have bugs in the math code. Let's see that maintenance programmer try to fix some of those. Sean
Nov 02 2001
Walter wrote:While operator overloading is an idea with many merits, I just don't see that arbitrary operators with arbitrary precedence would lead to something that wouldn't be better done with YACC.Much of the operator overloading I've seen often appears to be little more than a wish for an infix notation, to use instead standard functional call notation used to invoke a two parameter function. Rather than directly support operator overloading, why not support a generic infix function call? So, instead of: val = pow(2,10); We could have: val = 2 pow 10; Then, if I wish to "overload" the multiplication operator, I might do something like this: myType x(myType a, myType b) infix { return <however these two types multiply>; } And use it like this: product = varA x varB; For functions of two parameters, perhaps the infix form can be unambiguously detected by its use, and no "infix" keyword or declaration syntax will be needed. Be sure to give user-defined infix operators the lowest possible precedence, which should also encourage the use of parentheses to clarify such notation. Is this Food or Fluff? It certainly is Syntactic Sugar, but it looks sweet to me... -BobC
Nov 03 2001
I agree. I suggested something like this. see Operator overloading, ann other idea Ciao Roland "Robert W. Cunningham" a écrit :Walter wrote:While operator overloading is an idea with many merits, I just don't see that arbitrary operators with arbitrary precedence would lead to something that wouldn't be better done with YACC.Much of the operator overloading I've seen often appears to be little more than a wish for an infix notation, to use instead standard functional call notation used to invoke a two parameter function. Rather than directly support operator overloading, why not support a generic infix function call? So, instead of: val = pow(2,10); We could have: val = 2 pow 10; Then, if I wish to "overload" the multiplication operator, I might do something like this: myType x(myType a, myType b) infix { return <however these two types multiply>; } And use it like this: product = varA x varB; For functions of two parameters, perhaps the infix form can be unambiguously detected by its use, and no "infix" keyword or declaration syntax will be needed. Be sure to give user-defined infix operators the lowest possible precedence, which should also encourage the use of parentheses to clarify such notation. Is this Food or Fluff? It certainly is Syntactic Sugar, but it looks sweet to me... -BobC
Nov 05 2001
So, instead of: val = pow(2,10); We could have: val = 2 pow 10;The problem arises what is if you have: x = 2 pow 10 pow 3; Should it do pow(pow(2 , 10), 3) , or pow(2, pow(10, 3)) ? or with x = 2 pow 3 x 4 * 2 + 7 % 3 pow 8; How do you define and sort priority of these new infix functions? Additionally you should be able to tell the compiler which rules this operation follows, is it communative? associative? can he extract common arguments? like a * b + a * c => a * (b + c). I think a general operator decleration and ruling system is something nobody yet managed to design/implement. - Axel -- |D) http://www.dtone.org
Nov 05 2001
This problem could not be soulved by defining operator precedence levels ? e.g : Level 1 -------------------- ~ , ^ , &, ando anothers Level 3 -------------------- * / % Level 5 -------------------- + - Level 7 -------------------- * / % Level 9 -------------------- == != > < Two or more operator in same level can be operated in any order. Your infix fuction level must be in ( 0..10 ).So, instead of: val = pow(2,10); We could have: val = 2 pow 10;The problem arises what is if you have: x = 2 pow 10 pow 3; Should it do pow(pow(2 , 10), 3) , or pow(2, pow(10, 3)) ? or with x = 2 pow 3 x 4 * 2 + 7 % 3 pow 8; How do you define and sort priority of these new infix functions? Additionally you should be able to tell the compiler which rules this operation follows, is it communative? associative? can he extract common arguments? like a * b + a * c => a * (b + c). I think a general operator decleration and ruling system is something nobody yet managed to design/implement. - Axel "Axel Kittenberger" <axel dtone.org> wrote in message news:9s62ji$1hoh$1 digitaldaemon.com...So, instead of: val = pow(2,10); We could have: val = 2 pow 10;The problem arises what is if you have: x = 2 pow 10 pow 3; Should it do pow(pow(2 , 10), 3) , or pow(2, pow(10, 3)) ? or with x = 2 pow 3 x 4 * 2 + 7 % 3 pow 8; How do you define and sort priority of these new infix functions? Additionally you should be able to tell the compiler which rules this operation follows, is it communative? associative? can he extract common arguments? like a * b + a * c => a * (b + c). I think a general operator decleration and ruling system is something nobody yet managed to design/implement. - Axel -- |D) http://www.dtone.org
Nov 05 2001
I think I'd rather deal with precedence in terms of existing operators in the language. i.e. give my new super_plus operator the same precedence as operator +, or maybe give my dot product operator a higher precedence than operator *, but lower than unary &. In fact though I wouldn't mind having to use explicit parens around my expressions for now until someone works out a good system for this. I like the commutative/associative modifiers (there are more, but I'm no mathematician) because they give the compiler hints about how it can rearrange expressions during optimization, something it does know about the builtin operators. M1 * M2 != M2 * M1 when M is a matrix, or a quaternion. The big problem to be solved here is how can you make a language parser that can insert arbitrary grammar pieces into the parser during compilation, in fact it would have to be done only within a certain scope. Even more troublesome is that a symbol may not be visible in the source file; it'd have to be able to change the grammar to add these operators whenever it detects a scope has been accessed/entered during parsing of an expression. Another big problem for operator overloading is how to deal with promotion of arguments. Ideally this could be done by stating a preference for one typecast direction over another, thus preferring float->double as safer than double->float for instance, char->int as safer than int->char, so that if it sees 'R' plus 43 it'll know to promote the 'R' to int instead of vice-versa. I'm disappointed that there will likely be no operator overloading in D 1.0. Sean "Juarez Rudsatz" <juarez mpsinf.com.br> wrote in message news:9s6dbf$1pv9$1 digitaldaemon.com...This problem could not be soulved by defining operator precedence levels ? e.g : Level 1 -------------------- ~ , ^ , &, ando anothers Level 3 -------------------- * / % Level 5 -------------------- + - Level 7 -------------------- * / % Level 9 -------------------- == != > < Two or more operator in same level can be operated in any order. Your infix fuction level must be in ( 0..10 ).So, instead of: val = pow(2,10); We could have: val = 2 pow 10;The problem arises what is if you have: x = 2 pow 10 pow 3; Should it do pow(pow(2 , 10), 3) , or pow(2, pow(10, 3)) ? or with x = 2 pow 3 x 4 * 2 + 7 % 3 pow 8; How do you define and sort priority of these new infix functions? Additionally you should be able to tell the compiler which rules this operation follows, is it communative? associative? can he extract common arguments? like a * b + a * c => a * (b + c). I think a general operator decleration and ruling system is something nobody yet managed to design/implement. - Axel "Axel Kittenberger" <axel dtone.org> wrote in message news:9s62ji$1hoh$1 digitaldaemon.com...So, instead of: val = pow(2,10); We could have: val = 2 pow 10;The problem arises what is if you have: x = 2 pow 10 pow 3; Should it do pow(pow(2 , 10), 3) , or pow(2, pow(10, 3)) ? or with x = 2 pow 3 x 4 * 2 + 7 % 3 pow 8; How do you define and sort priority of these new infix functions? Additionally you should be able to tell the compiler which rules this operation follows, is it communative? associative? can he extract common arguments? like a * b + a * c => a * (b + c). I think a general operator decleration and ruling system is something nobody yet managed to design/implement. - Axel -- |D) http://www.dtone.org
Nov 05 2001
If the C++ overloading doesn't work well, then look at other languages. This is one thing that Eiffel handles fairly well (though I was at one point ungruntled after it refused to allow = [i.e., test for equality] to be overridden).
Aug 17 2001
Eiffel seems to do a lot of things well that C++ doesn't. But I'm a bigot - I can't stand that pascal-esque sytnax =) "Charles Hixson" <charleshixsn earthlink.net> wrote in message news:3B7D2D68.4080905 earthlink.net...If the C++ overloading doesn't work well, then look at other languages. This is one thing that Eiffel handles fairly well (though I was at one point ungruntled after it refused to allow = [i.e., test for equality] to be overridden).
Aug 18 2001
kaffiene wrote:Eiffel seems to do a lot of things well that C++ doesn't. But I'm a bigot - I can't stand that pascal-esque sytnax =) ...Eiffel is much less flexible in many ways than C++. This is both good and bad. The syntax doesn't matter that much if we are mining it for features to include in a new language. Not unless we consider the syntax as one of the features that we are mining. Actually, in the case of generics, the syntax might be worth mining. It's a lot better than the template notation, and does most of the same job. And there's not too much wrong with the way that it declares operators (an infix operator is a function with one return value and two parameters, one implicitly specified by the class that contains it and one explicitly specified. In the declaration the keyword infix is used preceeding the name of the operator in quotes.), but the way that Ada does it is as reasonable, and the way that C++ does it is probably more familiar.
Aug 21 2001
"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:3B828CC2.70706 earthlink.net...kaffiene wrote:bigot -Eiffel seems to do a lot of things well that C++ doesn't. But I'm aOh sure! That's exactly what I meant - I like a lot of the ideas in Eiffel. I just don't use it because of the syntax. Peter.I can't stand that pascal-esque sytnax =) ...Eiffel is much less flexible in many ways than C++. This is both good and bad. The syntax doesn't matter that much if we are mining it for features to include in a new language. Not unless we consider the syntax as one of the features that we are mining.
Aug 21 2001
kaffiene wrote:(4) It introduces another style for doing very common stuff. One group of programmers does vec.plus(v2) and another does vec + v2.Without overloading, one group does vec.plus(v2), another does vec.add(v2). It's like in the Java API, you have add() for Vectors and put() for Hashtables -- consistent naming is hard to enforce and something always goes wrong. If there is an "obvious" name like +, surely it's better to use that (even at the risk of idiots defing it in "non-obvious" ways...)? ----------------------------------------------------------------- John English | mailto:je brighton.ac.uk Senior Lecturer | http://www.it.bton.ac.uk/staff/je Dept. of Computing | ** NON-PROFIT CD FOR CS STUDENTS ** University of Brighton | -- see http://burks.bton.ac.uk -----------------------------------------------------------------
May 03 2002
"John English" <je brighton.ac.uk> wrote in message news:3CD27936.7152F760 brighton.ac.uk...kaffiene wrote:of(4) It introduces another style for doing very common stuff. One groupThis discussion is periodically returning here. I am in favour of operator overloading for exactly this reason. Common stuff, such as adding things already have very common and standardized 'names' in math, +, -, * and /. With named functions, you can get: vec1.Add (vec2); // seems logical right? vec1.add (vec2); // Argh, we are case sensitive... vec1.Plus (vec2); // Mmm makes sense too right? vec1.And (vec2) // And this too... vec1.Und (vec2); // written by a german :) vec1.En (vec2); // Or by a dutchmen... Need I go on? + is + and math is math. If you are a programmer you must know math, period. Ofcourse + could be interpreted to mean something different by different people, but this also goes for named functions. What does matrix1.Mul (matrix2) mean? Does it do a cross product? It seems to me operator overloading solves some problems and introduces some others, but one of the things it does solve is allow the use of a common language for describing mathematical operations, not english, german or dutch, but math itself! If you are interested, read the thread "Operator overloading, a way to make everybody happy', it talks about many of these things, Don't be afraid of a little flaming here and there though. In abovementioned thread I proposed a way where standard interfaces would be defined for supporting common math operations, such as IAddable, IAssignable, IComparable etcetera. The compiler would then map the operators =, ==, <, >, +, -, / and * to these interfaces, creating some sweet syntax sugar. Walter has implemented a tweaked version of this for the comparison operators, where the base class Object contains functions cmp() and equals() for comparison and for testing for equality. The compiler then maps the operators <, <=, > and >= to cmp() and == and != to equals(). You can overload the functions cmp() and equals() and you will then automagically overload the comparison operators too! At the moment there is no operator overloadin support for assignment. A big problem with this is how to distinguish between assignment by reference and by value. I proposed using = for assignment by reference and := for assignment by value, but this has not meet with enthousiastic reception (and for obvious reasons...). At the moment you will need to call dup(), but at least it is standard for all objects. For addition, subtraction, multiplication and division all bets are off, but this might change quick, like it has done with the overloading of the comparison operators and with the inclusion of delegates.. :) Fingers crossed... :) -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mailprogrammers does vec.plus(v2) and another does vec + v2.Without overloading, one group does vec.plus(v2), another does vec.add(v2). It's like in the Java API, you have add() for Vectors and put() for Hashtables -- consistent naming is hard to enforce and something always goes wrong. If there is an "obvious" name like +, surely it's better to use that (even at the risk of idiots defing it in "non-obvious" ways...)?
May 05 2002
As someone who writes tons of vector math code in production applications, my feeling is that a language which doesn't support operator overloading and template-style programming is really going to be really painful for moden math-intensive applications, such as games, modelling programs, etc. I'm not necessarily advocating C++'s approach (operator overloading can be confusing, such as using an overloaded "<<" operator to represent both bit shifting and character output!) Haskell-style "typeclasses" are an interesting replacement for general operator overloading. This approach encapsulates the idea that a given operator like "+" or "*" should have the same notional meaning everywhere, even when operating on different data types. A simple example is that "+" and "*" would belong to the "numeric" typeclass. If you create a new numeric typeclass of your own (for example, a "bigint" class), then you declare your class to belong to the "numeric" typeclass, and implement those specific operators. However, you wouldn't be able to create a "+" operator for a non-numeric class. This can map to popular languages easily by having your class implement an abstract interface (aka typeclass) and provide an appropriate static or friend function for those operators. However, this approach doesn't extend well to more general situations. For example, say you define a template like vector<float,4> (a mathematical 4-component vector), one wants the ability to multiply those vectors by scalars using "*", which requires the more general form of overloading. -Tim "John Fletcher" <J.P.Fletcher aston.ac.uk> wrote in message news:3B78E154.BC62E006 aston.ac.uk...Quote from the specification for D: Operator overloading. The only practical applications for operator overloading seem to be implementing a complex floating point type, a string class, and smart pointers. D provides the first two natively, smart pointers are irrelevant in a garbage collected language. Another quote: D has many features to directly support features needed by numerics programmers, like direct support for the complex data type and defined behavior for NaN's and infinities. Comment: For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable. John Fletcher
Aug 17 2001
I'll second this. I understand that C++ overloads are insuficant but ugly, but this might be a case to find a better solution. I like the suggestion of the 'written' syntax. It is powerful but could blow off several toes if aimed at one's foot. It might be nice to declare a precedence level for new ops, that way if you define a 'dot' infix expression you can say he has the precedence of a multiplication op. At the very least, I would like to see D better address matrix math (quaternions too) and arbitrary sized numbers. Dan John Fletcher wrote:Quote from the specification for D: Operator overloading. The only practical applications for operator overloading seem to be implementing a complex floating point type, a string class, and smart pointers. D provides the first two natively, smart pointers are irrelevant in a garbage collected language. Another quote: D has many features to directly support features needed by numerics programmers, like direct support for the complex data type and defined behavior for NaN's and infinities. Comment: For numerical computing it is convenient to define classes e.g. vectors, matrices and other entities beyond complex numbers, such as quaternions. For this overloading of operators such as +, -, +=, etc means that top level code can be easily written and readable. John Fletcher
Aug 18 2001
a wrote:I like the suggestion of the 'written' syntax. It is powerful but could blow off several toes if aimed at one's foot.Why? Could you give an example? Christophe
Aug 20 2001
Christophe de Dinechin wrote:a wrote:It's hard to give an example without a concrete syntax to start with. (Christophe, you might also remember that I'm bad at examples. :) One case I'm thinking of would be unexpected ambiguity like: typedef int[3] vec; typedef double scalar; vec build_vec(scalar larry, scalar curly, scalar moe) written ( larry curly moe ) { return { larry, curly, moe }; // I know this array syntax wouldn't } // but wouldn't it would be nice? scalar abs(vec tor) written || tor || { // using the sqrt syntax I defined as \/ <exp> | return \/tor[0] * tor[0] + tor[1] * tor[1] + tor[2] * tor[2] |; } scalar x = 0; scalar z = 1.0; vec why = {1, 1, 1} // NOTE: I'm assuming that abs is defined for built in types like int int it = abs( x || why || z ); // and that bool could cast to int What is it? Is it 0 since x could short circuit the '||' or is it sqrt(0, sqrt(3), 1). It could reasonably be either. You might be able to build a compiler that could brute force through and catch all the possible ambiguities in a given piece of code, but you could still end up with libraries that can't be used together do to a nasty mix of poorly chosen written clauses. Don't get me wrong. I like the feature. It's just like many of C++'s (or perl's) features. Beautiful when used right and dangerous if used wrong. The same it true of C++'s operator overloads, but man they are handy at times. The ability to say: written A * B + C written (A * B) + C or the like would have made libraries like blitz++ a lot easier to do I bet. I suspect they would have made the templates less necessary, making the compile times faster. But Walter seems to favor safety and simpler implementation. This probably crosses a line for him. Cheers, DanI like the suggestion of the 'written' syntax. It is powerful but could blow off several toes if aimed at one's foot.Why? Could you give an example? Christophe
Aug 21 2001