D - infix functions as a substitute for operator overloading?
- Richard Krehbiel (33/33) Feb 13 2002 My thinking: Why does operator overloading exist?
- Russ Lewis (19/25) Feb 13 2002 Can you describe why this is impossible with YACC? As I understand it, ...
- Richard Krehbiel (51/71) Feb 13 2002 precedence
- Russ Lewis (9/12) Feb 13 2002 Gotcha! Now I understand.
- OddesE (14/21) Feb 17 2002 always
- Pavel Minayev (5/8) Feb 17 2002 He said "user-defined", not "built-in".
- Russ Lewis (11/14) Feb 18 2002 Right. I would say that any overloading of standard operators (with or
- OddesE (16/30) Feb 18 2002 Oh I'm sorry, I understood wrong.
- Pavel Minayev (4/8) Feb 13 2002 operation,
- Russell Borogove (28/43) Feb 13 2002 For a second, I thought Richard's suggestion was a valuable
- OddesE (9/18) Feb 17 2002 Me too!
- Roland (6/20) Feb 13 2002 I already suggested something like this (see "Operator overloading, ann ...
My thinking: Why does operator overloading exist? I think the primary reason is to allow an infix notation for user-defined functions. Common compiler construction technology (YACC, PCCTS) requires the syntax be fixed; the set of infix tokens is fixed, their precedence is fixed, their associativity is fixed. But maybe we've progressed beyond that. What if it were possible for the user to simply declare a function as "infix?" infix int plus(int a, int b) { return a + b; } Now you can code: int x, y, z; z = x plus y; Pretty readable. Clearly "plus" is a user- (or library-) defined operation, and I *like* making that clear to the reader. That leaves precedence and associativity. Right now I'd guess that it would be okay if all infix operators would have lower precedence than all built-in operators. We can also simplify by giving all infix functions equal precedence, and make the user group them as needed by parentheses, but it might be nice to be able to specify their associativity (does "a plus b plus c" do "b plus c" first, or "a plus b" first?). Now, ISTR that the current alpha D compiler is a hand-coded recursive-descent parser, and I'm pretty sure that a smart man like Walter could in fact code up syntactic analyser that is tolerant of additions to the infix operator table (eh, Walter?). But it means you can't build D compilers with YACC (um, maybe; if you leave out user control of precedence and associativity, I think it could still be done). Oh, and it means feeding back info from semantic analysis into syntax, and I recall reading that Walter has decided this is bad (the reasoning for his syntactic changes to type-casting operations). Well, it was a thought. -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 home.com (personal)
Feb 13 2002
Richard Krehbiel wrote:But it means you can't build D compilers with YACC (um, maybe; if you leave out user control of precedence and associativity, I think it could still be done). Oh, and it means feeding back info from semantic analysis into syntax, and I recall reading that Walter has decided this is bad (the reasoning for his syntactic changes to type-casting operations).Can you describe why this is impossible with YACC? As I understand it, what YACC really sees is <token> = <token> <token> <token> ; Which it would parse into blocks something like blockA: x plus y blockB: z = <blockA> blockC: <blockB> ; It's the responsibility of the compiler code supplied with the blockA rule to determine what those 3 alphanumeric tokens mean. It's not particularly different from foo bar; which the compiler must deduce (from semantics) is a variable declaration. Maybe I'm missing something again... -- 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))) ]
Feb 13 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C6A7779.27137005 deming-os.org...Richard Krehbiel wrote:precedenceBut it means you can't build D compilers with YACC (um, maybe; if you leave out user control ofreadingand associativity, I think it could still be done). Oh, and it means feeding back info from semantic analysis into syntax, and I recallchangesthat Walter has decided this is bad (the reasoning for his syntacticwhatto type-casting operations).Can you describe why this is impossible with YACC? As I understand it,YACC really sees is <token> = <token> <token> <token> ; Which it would parse into blocks something like blockA: x plus y blockB: z = <blockA> blockC: <blockB> ; It's the responsibility of the compiler code supplied with the blockA ruletodetermine what those 3 alphanumeric tokens mean. It's not particularly different from foo bar; which the compiler must deduce (from semantics) is a variable declaration. Maybe I'm missing something again...Here's a YACC (like) expression of some of the C grammar, taken from the back of K&R's "The C Programming Language:" shift_expr: add_expr | shift_expr '<<' add_expr | shift_expr '>>' add_expr; add_expr: mul_expr | add_expr '+' mul_expr | add_expr '-' mul_expr; mul_expr: cast_expr | mul_expr '*' cast_expr | mul_expr '/' cast_expr | mul_expr '%' cast_expr; Precedence is defined in the grammar, that is, the grammar (which can't be changed at run time) defines that a mul_expr has higher precedence than add_expr and shift_expr (so "a + b * c" evaluates as "a + (b * c)"). Associativity is also defined in the grammar. Associativity says that if you have "a + b - c" it's evaluated as "(a + b) - c" (um, probably; C can reorder these, and you can tell by side-effects, if it can prove that otherwise the result is indistinguishable - and if overflow is possible, then it can be). Associativity matters a great deal if the side effects matter, like with the C++ "<<" iostream operator. When you code 'cout << "result is " << i << endl;', the output must go left-to-right. What I was saying is, if we rule that user-defined infix operators always and forever have a particular precedence and associativity, then we *can* build such a compiler with YACC. Assuming that the above was the top of the "expression" definition (it's not), we'd add: user_infix_expr: shift_expr | user_infix_expr INFIX_TOKEN shift_expr; And then, we'd tell the lexer that user-defined infix function names be returned as INFIX_TOKEN rather than as IDENTIFIER_TOKEN. Now, with a recursive-descent parser written in plain C, precedence and associativity rules could also be changed at run time. But you still need to know it's an "infix operator", not an "identiier", which means feedback. (...and I'm sure that *real* compiler designers will correct any of this that's wrong...) -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 home.com (personal)
Feb 13 2002
Richard Krehbiel wrote:What I was saying is, if we rule that user-defined infix operators always and forever have a particular precedence and associativity, then we *can* build such a compiler with YACC.Gotcha! Now I understand. Frankly, it seems like left-to-right precedence/associativity makes sense for the majority of applications. Anybody got (good) counterexamples? -- 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))) ]
Feb 13 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C6A891A.A5881559 deming-os.org...Richard Krehbiel wrote:alwaysWhat I was saying is, if we rule that user-defined infix operators*can*and forever have a particular precedence and associativity, then weforbuild such a compiler with YACC.Gotcha! Now I understand. Frankly, it seems like left-to-right precedence/associativity makes sensethe majority of applications. Anybody got (good) counterexamples?CInt256 a = 1, b = 2, c = 5; a = a + b * c; // Should yield 11, not 15.... -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 17 2002
"OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a4o5g5$rgm$1 digitaldaemon.com...CInt256 a = 1, b = 2, c = 5; a = a + b * c; // Should yield 11, not 15....He said "user-defined", not "built-in". For user-defined, I guess we can live with fixed precedence, using braces where necessary...
Feb 17 2002
Pavel Minayev wrote:He said "user-defined", not "built-in". For user-defined, I guess we can live with fixed precedence, using braces where necessary...Right. I would say that any overloading of standard operators (with or without the :'s that have been suggested) should have the same precedence and left-to-right orientation as the original operators. But user-defined infix operators of this type should all have left-to-right orientation with relatively low precedence. -- 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))) ]
Feb 18 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C70B980.E4FD2FA1 deming-os.org...Pavel Minayev wrote:Oh I'm sorry, I understood wrong. I think user defined infix operations would be cool and I could live with fixed left to right precedence without a problem. I thought it was proposed as a substitution for overloading the standard operators, but I agree that you shouldn't mess with the precedence of + and *, or many people will be very confused and that can't be what we are aiming at with operator overloading. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mailHe said "user-defined", not "built-in". For user-defined, I guess we can live with fixed precedence, using braces where necessary...Right. I would say that any overloading of standard operators (with or without the :'s that have been suggested) should have the same precedence and left-to-right orientation as the original operators. But user-defined infix operators of this type should all have left-to-right orientation with relatively low precedence. -- 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))) ]
Feb 18 2002
"Richard Krehbiel" <rich kastle.com> wrote in message news:a4dqip$28i7$1 digitaldaemon.com...int x, y, z; z = x plus y; Pretty readable. Clearly "plus" is a user- (or library-) definedoperation,and I *like* making that clear to the reader.Hey, I still want to be able to overload + as is! =)
Feb 13 2002
Pavel Minayev wrote:"Richard Krehbiel" <rich kastle.com> wrote in message news:a4dqip$28i7$1 digitaldaemon.com...For a second, I thought Richard's suggestion was a valuable compromise. But when you think about it, it just _looks_ like... I don't know. Baby talk. Training wheels. Writing with crayon. (No offense intended.) Once you start trying to write a big hairy expression with "plus", you're going to want to rename it "pl" then "p" (or "add", then "a") to save space on the line. At that point you've hurt readability more than if you had overloaded the plus sign. Likewise, you still can't reasonably enforce against writing a "plus" function that, say, appends to a file on the disk. So who are we kidding? Unless you're going to vastly alter the way D is specified now, Walter, there are going to be a million ways to write misleading and crappy code. Giving us overloaded operators in the style of C++[1], or not, isn't materially going to change that. Many people want the overloaded operators. I don't know what other arguments I can make. Okay, okay, here's one more. Bignums. If I want to create a class that manages arbitrary- precision, arbitrary-magnitude numbers, I want to manipulate them using the conventional mathematical operators. :+: and other weirdness isn't going to help readability. -Russell B [1] And by that I mean without substantially restricting the operator list from C++ -- sure, get rid of . and -> and , but leave the bitwise, logical, and comparison operators in.int x, y, z; z = x plus y; Pretty readable. Clearly "plus" is a user- (or library-) definedoperation,and I *like* making that clear to the reader.Hey, I still want to be able to overload + as is! =)
Feb 13 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a4duo0$2ao6$1 digitaldaemon.com..."Richard Krehbiel" <rich kastle.com> wrote in message news:a4dqip$28i7$1 digitaldaemon.com...Me too! -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mailint x, y, z; z = x plus y; Pretty readable. Clearly "plus" is a user- (or library-) definedoperation,and I *like* making that clear to the reader.Hey, I still want to be able to overload + as is! =)
Feb 17 2002
Richard Krehbiel a écrit :My thinking: Why does operator overloading exist? I think the primary reason is to allow an infix notation for user-defined functions. Common compiler construction technology (YACC, PCCTS) requires the syntax be fixed; the set of infix tokens is fixed, their precedence is fixed, their associativity is fixed. But maybe we've progressed beyond that. What if it were possible for the user to simply declare a function as "infix?" infix int plus(int a, int b) { return a + b; } Now you can code: int x, y, z; z = x plus y; Pretty readable. Clearly "plus" is a user- (or library-) defined operation, and I *like* making that clear to the reader.I already suggested something like this (see "Operator overloading, ann other idea"). I was not convinced by counter arguments. So i still support infix notation Roland
Feb 13 2002