digitalmars.D - D and expression evaluation order.
- Bruno Medeiros (25/25) Apr 26 2007 As we know, in C/C++ there are a lot of cases where the order of
- Frits van Bommel (18/45) Apr 26 2007 Actually, if I read that right it just says that the order of evaluation...
- Bruno Medeiros (15/62) Apr 26 2007 Read the paragraph ahead in the doc. In D that is considered a
- =?UTF-8?B?THXDrXMgTWFycXVlcw==?= (6/9) Apr 26 2007 The compiler can only detect some cases, kind of like constant folding,
- Frits van Bommel (16/54) Apr 26 2007 IIRC[1] the C++ standard includes "causes a compile error" as one of the...
- Bruno Medeiros (21/75) Apr 27 2007 I haven't read about C++ in detail, only C. But in both cases (and
- Frits van Bommel (6/22) Apr 27 2007 Yes, if you depend on it then it indeed matters.
- James Dennett (29/78) Apr 27 2007 The difference is huge, not subtle. Using undefined
- Manfred Nowak (8/9) Apr 26 2007 - if a coder wants to define an order, she/he is free to use an
- =?ISO-8859-1?Q?Lu=EDs_Marques?= (9/15) Apr 26 2007 If there weren't performance issues I don't think there would be any
- =?ISO-8859-1?Q?Lu=EDs_Marques?= (9/15) Apr 26 2007 If there weren't performance issues I don't think there would be any
- Walter Bright (4/6) Apr 26 2007 I want to do that eventually, but it isn't easy to do. (There are also
- Russell Lewis (10/17) Apr 26 2007 To me, this sounds like a slam-dunk argument for never defining an
- Manfred Nowak (6/7) Apr 26 2007 This is not an issue, because the requirement is to define an order for
- Russell Lewis (5/13) Apr 27 2007 I don't understand what you're saying here; perhaps your definition was
- Sean Kelly (7/22) Apr 27 2007 It's an issue because it's confusing, as previous discussions can
- Russell Lewis (4/9) Apr 27 2007 Maybe a simpler solution (harder for Walter, probably, but simpler for
- Bruno Medeiros (7/33) Apr 27 2007 What do you mean by "most other languages"? Have you seen my other post
- Sean Kelly (7/18) Apr 27 2007 True. I suppose I should have said "most other languages I've used" :-p...
- Bruno Medeiros (8/29) Apr 29 2007 C# does support operator overload. Dunno about Python and Ruby.
- Daniel Keep (19/25) Apr 29 2007 def __init__(self, v):
- Jan Claeys (6/23) Apr 29 2007 Python supports operator overloading and "multiple calling
- Sean Kelly (5/25) Apr 30 2007 Ah well :-) I suppose I'm just worried we'd be trading away a potential...
- Manfred Nowak (21/36) Apr 27 2007 Have a look at one of Brunos examples:
- Manfred Nowak (14/15) Apr 26 2007 If it is not easy to define the order for the specs,
- Walter Bright (2/7) Apr 26 2007 It's easy to define the order. It is not so easy to implement it.
- Manfred Nowak (3/4) Apr 26 2007 Then please do so right now.
- Walter Bright (2/6) Apr 26 2007 Then I'd have a pile of bug reports because it isn't so easy to implemen...
- Manfred Nowak (6/8) Apr 26 2007 Why that, when it isn't in the specs, only in this forum, and declared
- Chris Nicholson-Sauls (5/17) Apr 26 2007 I don't think he means bugs in users' code (although there would probabl...
- Bruno Medeiros (34/46) Apr 27 2007 Someone with a non-low average thinking capability (*grin* :) ) would
- Russell Lewis (14/47) Apr 27 2007 Be careful when you imply "everybody who thinks differently than I is
- Manfred Nowak (15/23) Apr 27 2007 You require all operators to have an associativity? Then what is the
- Bruno Medeiros (9/18) Apr 29 2007 Huh? "require all operators to have an associativity"?... Any C-based
- Manfred Nowak (7/8) Apr 29 2007 | Comparison operators are no longer associative
- Bruno Medeiros (13/25) May 01 2007 Hum, you're right, I forgot about that, sorry.
- Manfred Nowak (13/16) May 01 2007 Don't you see a reason why Walter has tossed himself out of this
- Benji Smith (3/4) May 01 2007 That's a great phrase! I'm stealing it for my own purposes :-) Thanks!
- Bruno Medeiros (15/36) May 06 2007 Hum, good point. This looks like an unprecedented case, I don't know if
- Daniel Keep (22/24) May 06 2007 Rubbish. Python does as well, and for precisely the same reason I
- Manfred Nowak (6/7) May 07 2007 There is at least one more such decision to be made.
- janderson (12/35) Apr 26 2007 I agree. Furthermore, I strongly think it should be left as is. Why,
- Dan (4/4) Apr 28 2007 I tend to think if it's ambiguous it shouldn't be allowed. I most defin...
As we know, in C/C++ there are a lot of cases where the order of evaluation of an expression is undefined. i = i++; c = a + (a = b); func(++i, ++i); D goes one step further by defining that any such behavior is illegal: "Unless otherwise specified, the implementation is free to evaluate the components of an expression in any order. It is an error to depend on order of evaluation when it is not specified." in http://www.digitalmars.com/d/expression.html . That's nice, but why not go all the way, and actually define an evaluation order for such expressions. There is nothing to lose, and it should be easy to implement. This is what Java does. For example, the following (which I found recently in JDT's code) is perfectly legal Java code: int length = array.length; ... System.arraycopy(array, 0, array = new IFoo[length + 1], 0, length); because Java not only defines that the argument evaluation order is left to right, but also that the arguments are bound to parameters as they are evaluated (and not after all are evaluated). The little details matter a lot. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Apr 26 2007
Bruno Medeiros wrote:As we know, in C/C++ there are a lot of cases where the order of evaluation of an expression is undefined. i = i++; c = a + (a = b); func(++i, ++i); D goes one step further by defining that any such behavior is illegal: "Unless otherwise specified, the implementation is free to evaluate the components of an expression in any order. It is an error to depend on order of evaluation when it is not specified." in http://www.digitalmars.com/d/expression.html .Actually, if I read that right it just says that the order of evaluation is undefined and should not be relied upon. Just like C/C++.That's nice, but why not go all the way, and actually define an evaluation order for such expressions. There is nothing to lose, and it should be easy to implement. This is what Java does. For example, the following (which I found recently in JDT's code) is perfectly legal Java code: int length = array.length; ... System.arraycopy(array, 0, array = new IFoo[length + 1], 0, length); because Java not only defines that the argument evaluation order is left to right, but also that the arguments are bound to parameters as they are evaluated (and not after all are evaluated). The little details matter a lot.Unspecified evaluation order is an optimization opportunity. For instance, the most efficient parameter evaluation order can be dependent on the calling convention, which is platform-dependent. For instance on x86 and amd64 platforms the most efficient evaluation order can very well be to evaluate right-to-left, since typical calling conventions specify the last argument is to be pushed onto the stack first[1]. (There are good reasons for that, mostly to do with varargs) DMD's extern(D) (i.e. the default) calling convention and GDC's amd64 calling convention are a slight variation on that, passing some arguments in a register if possible. It may for that reason be more efficient to evaluate those in another order so that those registers can be used in evaluation of other arguments. [1] Though on amd64 the first few arguments are typically passed in registers, and DMD by default passes one argument in a register as well, so the stack may not be used if there are few arguments.
Apr 26 2007
Frits van Bommel wrote:Bruno Medeiros wrote:Read the paragraph ahead in the doc. In D that is considered a language(i.e. compile) error and so the compiler can issue an error. In C/C++ it is merely undefined program behavior, the code remains compilable.As we know, in C/C++ there are a lot of cases where the order of evaluation of an expression is undefined. i = i++; c = a + (a = b); func(++i, ++i); D goes one step further by defining that any such behavior is illegal: "Unless otherwise specified, the implementation is free to evaluate the components of an expression in any order. It is an error to depend on order of evaluation when it is not specified." in http://www.digitalmars.com/d/expression.html .Actually, if I read that right it just says that the order of evaluation is undefined and should not be relied upon. Just like C/C++.In that case, it is possible for the compiler to detect if the evaluation order matters, and if it doesn't (currently the only allowed situation in D), it can push the arguments in any order it pleases him. Even if that wasn't possible, I'm not sure that with modern CPU technology, right-to-left calling conventions (last argument on top) would be any slower to call with an left-to-right eval order, than with an undefined order. Then again, I'm no Assembler or CPU optimization expert, so correct if I'm wrong. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DThat's nice, but why not go all the way, and actually define an evaluation order for such expressions. There is nothing to lose, and it should be easy to implement. This is what Java does. For example, the following (which I found recently in JDT's code) is perfectly legal Java code: int length = array.length; ... System.arraycopy(array, 0, array = new IFoo[length + 1], 0, length); because Java not only defines that the argument evaluation order is left to right, but also that the arguments are bound to parameters as they are evaluated (and not after all are evaluated). The little details matter a lot.Unspecified evaluation order is an optimization opportunity. For instance, the most efficient parameter evaluation order can be dependent on the calling convention, which is platform-dependent. For instance on x86 and amd64 platforms the most efficient evaluation order can very well be to evaluate right-to-left, since typical calling conventions specify the last argument is to be pushed onto the stack first[1]. (There are good reasons for that, mostly to do with varargs) DMD's extern(D) (i.e. the default) calling convention and GDC's amd64 calling convention are a slight variation on that, passing some arguments in a register if possible. It may for that reason be more efficient to evaluate those in another order so that those registers can be used in evaluation of other arguments.
Apr 26 2007
Bruno Medeiros wrote:In that case, it is possible for the compiler to detect if the evaluation order matters, and if it doesn't (currently the only allowed situation in D), it can push the arguments in any order it pleases him.The compiler can only detect some cases, kind of like constant folding, but it might aliviate many cases. Inter-module flow analysis would help here (coming soon with GCC, weee!) -- LuĂs
Apr 26 2007
Bruno Medeiros wrote:Frits van Bommel wrote:IIRC[1] the C++ standard includes "causes a compile error" as one of the possible consequences of undefined behavior. I'm not sure about C. [1] I've been staying away from C++ since I started using D, so this is by no means a given... [snip]Bruno Medeiros wrote:Read the paragraph ahead in the doc. In D that is considered a language(i.e. compile) error and so the compiler can issue an error. In C/C++ it is merely undefined program behavior, the code remains compilable.As we know, in C/C++ there are a lot of cases where the order of evaluation of an expression is undefined. i = i++; c = a + (a = b); func(++i, ++i); D goes one step further by defining that any such behavior is illegal: "Unless otherwise specified, the implementation is free to evaluate the components of an expression in any order. It is an error to depend on order of evaluation when it is not specified." in http://www.digitalmars.com/d/expression.html .Actually, if I read that right it just says that the order of evaluation is undefined and should not be relied upon. Just like C/C++.[snip]Unspecified evaluation order is an optimization opportunity. For instance, the most efficient parameter evaluation order can be dependent on the calling convention, which is platform-dependent. For instance on x86 and amd64 platforms the most efficient evaluation order can very well be to evaluate right-to-left, since typical calling conventions specify the last argument is to be pushed onto the stack first[1]. (There are good reasons for that, mostly to do with varargs)In that case, it is possible for the compiler to detect if the evaluation order matters, and if it doesn't (currently the only allowed situation in D), it can push the arguments in any order it pleases him.<nitpick> Actually, if you check the spec it says the compiler is allowed to issue an error if it detects the _result_ of the expression depends on evaluation order. It doesn't seem to mention side-effects at all, so evaluation order is technically allowed to matter (though it's still an error to _depend_ on it). Well, unless you count side-effects as part of the "result" of an expression... </nitpick>Even if that wasn't possible, I'm not sure that with modern CPU technology, right-to-left calling conventions (last argument on top) would be any slower to call with an left-to-right eval order, than with an undefined order. Then again, I'm no Assembler or CPU optimization expert, so correct if I'm wrong.Nor am I, but I've inspected a lot of the assembly code generated for my programs and often the DMD and GDC optimizers apparently decided to evaluate (roughly) right-to-left...
Apr 26 2007
Frits van Bommel wrote:Bruno Medeiros wrote:I haven't read about C++ in detail, only C. But in both cases (and sometimes here in the NG too) I often see the documents call "undefined behavior" to thing they should call errors. They refer to these concepts almost interchangeably, whereas they are not. They overlap a lot but they are not the same, there is a subtle difference. Dereferencing a trash pointer, for example, *is* an error. It *causes* undefined behavior, but it *is not* merely undefined behavior: it *can crash* your program. On the other hand if do: func(i++, i++); where func simply prints prints its arguments, I will have undefined program behavior, but no program error : that code *can not ever* crash the program. (altough it is still likely a *conceptual* error) This is a minor nitpick, since in practice both should be equally avoided, but that subtle difference is still there.Frits van Bommel wrote:IIRC[1] the C++ standard includes "causes a compile error" as one of the possible consequences of undefined behavior. I'm not sure about C. [1] I've been staying away from C++ since I started using D, so this is by no means a given...Bruno Medeiros wrote:Read the paragraph ahead in the doc. In D that is considered a language(i.e. compile) error and so the compiler can issue an error. In C/C++ it is merely undefined program behavior, the code remains compilable.As we know, in C/C++ there are a lot of cases where the order of evaluation of an expression is undefined. i = i++; c = a + (a = b); func(++i, ++i); D goes one step further by defining that any such behavior is illegal: "Unless otherwise specified, the implementation is free to evaluate the components of an expression in any order. It is an error to depend on order of evaluation when it is not specified." in http://www.digitalmars.com/d/expression.html .Actually, if I read that right it just says that the order of evaluation is undefined and should not be relied upon. Just like C/C++.[snip]To "depend on the evaluation order" is to have the evaluation order matter. :) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D[snip]Unspecified evaluation order is an optimization opportunity. For instance, the most efficient parameter evaluation order can be dependent on the calling convention, which is platform-dependent. For instance on x86 and amd64 platforms the most efficient evaluation order can very well be to evaluate right-to-left, since typical calling conventions specify the last argument is to be pushed onto the stack first[1]. (There are good reasons for that, mostly to do with varargs)In that case, it is possible for the compiler to detect if the evaluation order matters, and if it doesn't (currently the only allowed situation in D), it can push the arguments in any order it pleases him.<nitpick> Actually, if you check the spec it says the compiler is allowed to issue an error if it detects the _result_ of the expression depends on evaluation order. It doesn't seem to mention side-effects at all, so evaluation order is technically allowed to matter (though it's still an error to _depend_ on it). Well, unless you count side-effects as part of the "result" of an expression... </nitpick>
Apr 27 2007
Bruno Medeiros wrote:Frits van Bommel wrote:Yes, if you depend on it then it indeed matters. But the other way around is not necessarily true; I think you can have a program where evaluation order matters (e.g. different orders produce different output) without the correctness actually _depending_ on it. Both orders may be equally correct :).Bruno Medeiros wrote:To "depend on the evaluation order" is to have the evaluation order matter. :)In that case, it is possible for the compiler to detect if the evaluation order matters, and if it doesn't (currently the only allowed situation in D), it can push the arguments in any order it pleases him.<nitpick> Actually, if you check the spec it says the compiler is allowed to issue an error if it detects the _result_ of the expression depends on evaluation order. It doesn't seem to mention side-effects at all, so evaluation order is technically allowed to matter (though it's still an error to _depend_ on it). Well, unless you count side-effects as part of the "result" of an expression... </nitpick>
Apr 27 2007
Bruno Medeiros wrote:Frits van Bommel wrote:The difference is huge, not subtle. Using undefined behavior (unless you're writing non-portable code and your implementation offers an extension that defines it) is *always* an error of a serious kind. Many errors require diagnostics from a C or C++ compiler; UB does not place *any* requirement on a compiler, which is allowed to fail to translate the code, to issue error messages, or to generate code that does *anything*.Bruno Medeiros wrote:I haven't read about C++ in detail, only C. But in both cases (and sometimes here in the NG too) I often see the documents call "undefined behavior" to thing they should call errors. They refer to these concepts almost interchangeably, whereas they are not. They overlap a lot but they are not the same, there is a subtle difference.Frits van Bommel wrote:IIRC[1] the C++ standard includes "causes a compile error" as one of the possible consequences of undefined behavior. I'm not sure about C. [1] I've been staying away from C++ since I started using D, so this is by no means a given...Bruno Medeiros wrote:Read the paragraph ahead in the doc. In D that is considered a language(i.e. compile) error and so the compiler can issue an error. In C/C++ it is merely undefined program behavior, the code remains compilable.As we know, in C/C++ there are a lot of cases where the order of evaluation of an expression is undefined. i = i++; c = a + (a = b); func(++i, ++i); D goes one step further by defining that any such behavior is illegal: "Unless otherwise specified, the implementation is free to evaluate the components of an expression in any order. It is an error to depend on order of evaluation when it is not specified." in http://www.digitalmars.com/d/expression.html .Actually, if I read that right it just says that the order of evaluation is undefined and should not be relied upon. Just like C/C++.Dereferencing a trash pointer, for example, *is* an error. It *causes* undefined behavior, but it *is not* merely undefined behavior: it *can crash* your program.Undefined behavior, formally, always has that potential. (In fact, it might be reasonable to say that the only ways to "crash" a C or C++ program are through the use of undefined behavior, and it is certainly correct to say that a crash is always a permitted consequence of using undefined behavior.)On the other hand if do func(i++, i++); where func simply prints prints its arguments, I will have undefined program behavior, but no program error : that code *can not ever* crash the program. (altough it is still likely a *conceptual* error)It can crash your program, or cause it to fail to compile. It's undefined behavior. Undefined behavior, unless specifically allowed by your implementation, means that all bets are off. Optimizers can assume that you won't violate the sequence point rules, and can do unbounded things with that information (for example).This is a minor nitpick, since in practice both should be equally avoided, but that subtle difference is still there.Misunderstandings of what undefined behavior means are common, but I'm not sure that your message clarifies. (In C++ the order of evaluation is unspecified, not undefined; this can mean that some code fragments have UB because they violate rules on sequence points. This uses the terms as per the ISO C++ standard.) -- James
Apr 27 2007
Bruno Medeiros wrotedefine an evaluation order for such expressions- if a coder wants to define an order, she/he is free to use an appropriate sequence of assignments - if there is a predefined order, then -- that predefined order must be learned by everyone -- for every deviation of that order the appropriate sequence of assignments must be coded anyway -manfred
Apr 26 2007
Manfred Nowak wrote:- if a coder wants to define an order, she/he is free to use an appropriate sequence of assignments - if there is a predefined order, then -- that predefined order must be learned by everyone -- for every deviation of that order the appropriate sequence of assignments must be coded anywayIf there weren't performance issues I don't think there would be any reason for the order not to be fixed. If someone knew the order they could rely on it. If they didn't they could also order the assignments. I don't think average programmers using Java even notice they learned the evaluation order, they just do it intuitively. For Java, the safety is more important. For D performance is. -- Luís
Apr 26 2007
Manfred Nowak wrote:- if a coder wants to define an order, she/he is free to use an appropriate sequence of assignments - if there is a predefined order, then -- that predefined order must be learned by everyone -- for every deviation of that order the appropriate sequence of assignments must be coded anywayIf there weren't performance issues I don't think there would be any reason for the order not to be fixed. If someone knew the order they could rely on it. If they didn't they could also order the assignments. I don't think average programmers using Java even notice they learned the evaluation order, they just do it intuitively. For Java, the safety is more important. For D performance is. -- Luís
Apr 26 2007
Bruno Medeiros wrote:That's nice, but why not go all the way, and actually define an evaluation order for such expressions.I want to do that eventually, but it isn't easy to do. (There are also issues with making it work with a C back end, where the C optimizer reorders things according to what is legal C.)
Apr 26 2007
Walter Bright wrote:Bruno Medeiros wrote:To me, this sounds like a slam-dunk argument for never defining an evaluation order. Why prevent optimizers from doing all that they can conceive of? IMHO, the only places where you want to define evaluation order is when it makes the program clearer, and the examples given are (again, my opinion) examples of bad coding style. If you want to do something complex, then code the steps in different statements; then it's totally clear what you're trying to do - to both the compiler *and* the guy maintaining your code 10 years from now. RussThat's nice, but why not go all the way, and actually define an evaluation order for such expressions.I want to do that eventually, but it isn't easy to do. (There are also issues with making it work with a C back end, where the C optimizer reorders things according to what is legal C.)
Apr 26 2007
Russell Lewis wroteWhy prevent optimizers from doing all that they can conceive of?This is not an issue, because the requirement is to define an order for those cases only, where currently evaluation order matters. In all other cases the compiler is free to choose the optimum the same way it currently does. -manfred
Apr 26 2007
Manfred Nowak wrote:Russell Lewis wroteI don't understand what you're saying here; perhaps your definition was too indirect? What are you wanting to define orders for, and what not? Moreover, if it's not an issue, then why did Walter bring it up? Apparently it *is* an issue.Why prevent optimizers from doing all that they can conceive of?This is not an issue, because the requirement is to define an order for those cases only, where currently evaluation order matters. In all other cases the compiler is free to choose the optimum the same way it currently does.
Apr 27 2007
Russell Lewis wrote:Manfred Nowak wrote:It's an issue because it's confusing, as previous discussions can attest. I'm still not convinced that there is sufficient reason to define an evaluation order, since most other languages don't and it doesn't seem to be a problem, but I'll admit that it would make for less confusion. SeanRussell Lewis wroteI don't understand what you're saying here; perhaps your definition was too indirect? What are you wanting to define orders for, and what not? Moreover, if it's not an issue, then why did Walter bring it up? Apparently it *is* an issue.Why prevent optimizers from doing all that they can conceive of?This is not an issue, because the requirement is to define an order for those cases only, where currently evaluation order matters. In all other cases the compiler is free to choose the optimum the same way it currently does.
Apr 27 2007
Sean Kelly wrote:It's an issue because it's confusing, as previous discussions can attest. I'm still not convinced that there is sufficient reason to define an evaluation order, since most other languages don't and it doesn't seem to be a problem, but I'll admit that it would make for less confusion.Maybe a simpler solution (harder for Walter, probably, but simpler for everybody else) would be to have the compiler start issuing errors when these undefined syntaxes are used. :)
Apr 27 2007
Sean Kelly wrote:Russell Lewis wrote:What do you mean by "most other languages"? Have you seen my other post have well defined evaluation orders? -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DManfred Nowak wrote:It's an issue because it's confusing, as previous discussions can attest. I'm still not convinced that there is sufficient reason to define an evaluation order, since most other languages don't and it doesn't seem to be a problem, but I'll admit that it would make for less confusion. SeanRussell Lewis wroteI don't understand what you're saying here; perhaps your definition was too indirect? What are you wanting to define orders for, and what not? Moreover, if it's not an issue, then why did Walter bring it up? Apparently it *is* an issue.Why prevent optimizers from doing all that they can conceive of?This is not an issue, because the requirement is to define an order for those cases only, where currently evaluation order matters. In all other cases the compiler is free to choose the optimum the same way it currently does.
Apr 27 2007
Bruno Medeiros wrote:Sean Kelly wrote:True. I suppose I should have said "most other languages I've used" :-p I'm wondering if it's fair to include languages that don't support operator overloading though, or multiple calling conventions. Can a strong parallel be drawn between D and any of the languages you mention, insofar as this issue is concerned? SeanIt's an issue because it's confusing, as previous discussions can attest. I'm still not convinced that there is sufficient reason to define an evaluation order, since most other languages don't and it doesn't seem to be a problem, but I'll admit that it would make for less confusion.What do you mean by "most other languages"? Have you seen my other post have well defined evaluation orders?
Apr 27 2007
Sean Kelly wrote:Bruno Medeiros wrote:But I don't see how operator overloading or calling conventions would have any effect on having a completely defined expression order of evaluation. Indeed, I don't think it makes any difference. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DSean Kelly wrote:True. I suppose I should have said "most other languages I've used" :-p I'm wondering if it's fair to include languages that don't support operator overloading though, or multiple calling conventions. Can a strong parallel be drawn between D and any of the languages you mention, insofar as this issue is concerned? SeanIt's an issue because it's confusing, as previous discussions can attest. I'm still not convinced that there is sufficient reason to define an evaluation order, since most other languages don't and it doesn't seem to be a problem, but I'll admit that it would make for less confusion.What do you mean by "most other languages"? Have you seen my other all have well defined evaluation orders?
Apr 29 2007
Bruno Medeiros wrote:But I don't see how operator overloading or calling conventions would have any effect on having a completely defined expression order of evaluation. Indeed, I don't think it makes any difference.Python:def __init__(self, v): self.v = v def __add__(self, rhs): return FakeInt(self.v+rhs.v) def __str__(self): return str(self.v)class FakeInt:5 -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/FakeInt(2) + FakeInt(3)
Apr 29 2007
Op Fri, 27 Apr 2007 18:42:12 -0700 schreef Sean Kelly <sean f4.ca>:Bruno Medeiros wrote:Python supports operator overloading and "multiple calling conventions"? ;-) -- JanCSean Kelly wrote:True. I suppose I should have said "most other languages I've used" :-p I'm wondering if it's fair to include languages that don't support operator overloading though, or multiple calling conventions.It's an issue because it's confusing, as previous discussions can attest. I'm still not convinced that there is sufficient reason to define an evaluation order, since most other languages don't and it doesn't seem to be a problem, but I'll admit that it would make for less confusion.What do you mean by "most other languages"? Have you seen my other Ruby all have well defined evaluation orders?
Apr 29 2007
Jan Claeys wrote:Op Fri, 27 Apr 2007 18:42:12 -0700 schreef Sean Kelly <sean f4.ca>:Ah well :-) I suppose I'm just worried we'd be trading away a potential for optimization for support of a coding strategy that no one should be using anyway. SeanBruno Medeiros wrote:Python supports operator overloading and "multiple calling conventions"? ;-)Sean Kelly wrote:True. I suppose I should have said "most other languages I've used" :-p I'm wondering if it's fair to include languages that don't support operator overloading though, or multiple calling conventions.It's an issue because it's confusing, as previous discussions can attest. I'm still not convinced that there is sufficient reason to define an evaluation order, since most other languages don't and it doesn't seem to be a problem, but I'll admit that it would make for less confusion.What do you mean by "most other languages"? Have you seen my other Ruby all have well defined evaluation orders?
Apr 30 2007
Russell Lewis wroteManfred Nowak wrote:Have a look at one of Brunos examples: | c = a + (b = c); There seem to exist some cases where evaluation order matters. This is because the coder might have believed in evaluating this expression as the sequence: b = c; c = a + b; // c == a + c or as the sequence: c = a + b; b = c; // b == a + c which might be different, if one of the following conditions holds: a != 0 b != c If it can be deduced from the context, that none of this conditions holds, then there is no need to define an order and thus no need to "prevent optimizers from doing all that they can conceive of". OTOH if it can be deduced from the context, that at least one of this conditions might hold then Brunos requirement kicks in.Russell Lewis wroteI don't understand what you're saying here; perhaps your definition was too indirect? What are you wanting to define orders for, and what not?Why prevent optimizers from doing all that they can conceive of?This is not an issue, because the requirement is to define an order for those cases only, where currently evaluation order matters. In all other cases the compiler is free to choose the optimum the same way it currently does.Moreover, if it's not an issue, then why did Walter bring it up? Apparently it *is* an issue.I do not realize that Walter wants to extend Brunos requirement. -manfred
Apr 27 2007
Walter Bright wroteit isn't easy to doIf it is not easy to define the order for the specs, then it will not be easy to learn, then near to nobody will know of or rely on the definition in the specs. Remember that even M$ recommends to fully parenthese expressions <because others might not know how to evaluate expressions without parentheses>. You once said, that you want to prohibit the upcoming of D-guru's. But if you yourself are not able to immediately sketch such order here, then you have the proof of upcoming gurus. If it is not easy to code then above arguments holds for compiler writers too. -manfred
Apr 26 2007
Manfred Nowak wrote:Walter Bright wroteIt's easy to define the order. It is not so easy to implement it.it isn't easy to doIf it is not easy to define the order for the specs,
Apr 26 2007
Walter Bright wroteIt's easy to define the order.Then please do so right now. -manfred
Apr 26 2007
Manfred Nowak wrote:Walter Bright wroteThen I'd have a pile of bug reports because it isn't so easy to implement.It's easy to define the order.Then please do so right now.
Apr 26 2007
Walter Bright wroteThen I'd have a pile of bug reports because it isn't so easy to implement.Why that, when it isn't in the specs, only in this forum, and declared as a draft definition? Please do not declare that the thinking capabilities of average D-users are that low. -manfred
Apr 26 2007
Manfred Nowak wrote:Walter Bright wroteI don't think he means bugs in users' code (although there would probably be a handful of them, most likely quick-fixes though). I think he actually means bugs in the compiler, which are worth more time spent investigating implementation details to avoid. -- Chris Nicholson-SaulsThen I'd have a pile of bug reports because it isn't so easy to implement.Why that, when it isn't in the specs, only in this forum, and declared as a draft definition? Please do not declare that the thinking capabilities of average D-users are that low. -manfred
Apr 26 2007
Manfred Nowak wrote:Walter Bright wroteSomeone with a non-low average thinking capability (*grin* :) ) would easily deduce that the evaluation order will be the same as any other have all the same evaluation order). The rule in a general sense is: Evaluate operands in the same order as the associativity rule of the operator. So stuff like this: c = a + (b = c); evaluates in this order: a c b (b = c) a + (b = c) c c = a + (b = c) A function call, since it is basicly an operator that takes a function value and arguments as operands, works in the same rule. So: func(++i, ++c); evaluates: func ++i ++c func(++i, ++c) I don't think there is any significant learning process involved here. If you know the associativity rules (which you should), then the evaluation order is simply what naturally follows from there. You don't have to memorize a whole different set of rules. In fact the assignments are basicly the only operators where the operands are evaluated right-to-left. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DThen I'd have a pile of bug reports because it isn't so easy to implement.Why that, when it isn't in the specs, only in this forum, and declared as a draft definition? Please do not declare that the thinking capabilities of average D-users are that low. -manfred
Apr 27 2007
Bruno Medeiros wrote:Someone with a non-low average thinking capability (*grin* :) ) would easily deduce that the evaluation order will be the same as any other have all the same evaluation order). The rule in a general sense is:Be careful when you imply "everybody who thinks differently than I is stupid." I can confidently state that I have non-low average thinking capability, and it is far from clear to me. I had to look pretty hard at your analysis below to make sure that I knew what seemed so "obvious" to you. My simple question is: why are we worrying about defining the behavior of code snippets which are bad coding style? There are clearer, more explicit ways to accomplish the same task, that do not require that we define the order of operations.Evaluate operands in the same order as the associativity rule of the operator. So stuff like this: c = a + (b = c); evaluates in this order: a c b (b = c) a + (b = c) c c = a + (b = c) A function call, since it is basicly an operator that takes a function value and arguments as operands, works in the same rule. So: func(++i, ++c); evaluates: func ++i ++c func(++i, ++c) I don't think there is any significant learning process involved here. If you know the associativity rules (which you should), then the evaluation order is simply what naturally follows from there. You don't have to memorize a whole different set of rules. In fact the assignments are basicly the only operators where the operands are evaluated right-to-left.If there is no significant learning process involved, then why did you need to state it here? Surely everybody knew the rules already. If not everybody knew the rules, there is a learning process involved...and apparently it's nontrivial, at least to some people.
Apr 27 2007
Bruno Medeiros wroteEvaluate operands in the same order as the associativity rule of the operator.You require all operators to have an associativity? Then what is the associativity of the operators for comparison?So stuff like this: c = a + (b = c); evaluates in this order:Seems arbitrary choosen to me.A function call, since it is basicly an operator that takes a function value and arguments as operands, works in the same rule.I see now, that you want a defined order for all expressions. Then imagine an arbitrary sequence of assignments: are you able to identify the regions of that sequence that are in existence only because the coder wants to use an ordering other then the predefined? If you are able to do so and someone declares that he is not able to do so then how would you teach him that capability of yours? Please start immediately under the fiction, that I am not able to identify those regions. -manfred
Apr 27 2007
Manfred Nowak wrote:Bruno Medeiros wroteHuh? "require all operators to have an associativity"?... Any C-based language has an associativity rule for all operators! Didn't you know that?? The associativity for comparison operators is listed here: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B (it's the same in D) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DEvaluate operands in the same order as the associativity rule of the operator.You require all operators to have an associativity? Then what is the associativity of the operators for comparison?
Apr 29 2007
Bruno Medeiros wrote(it's the same in D)| Comparison operators are no longer associative changelog for D 1.007 Sadly you seem unwilling to state your capabilities with respect to identifying assignment subsequences wich can be specifically attributed. -manfred
Apr 29 2007
Manfred Nowak wrote:Bruno Medeiros wroteHum, you're right, I forgot about that, sorry. So, going back to your original question: Manfred Nowak wrote:(it's the same in D)| Comparison operators are no longer associative changelog for D 1.007Bruno Medeiros wroteOk, I understand the question. Very well, let's use a different learning rule: All operands are evaluated left to right, with the exception of the assignment operators which are evaluated right-to-left. I think it is even easier to learn than the previous one. Any problem with this one? -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DEvaluate operands in the same order as the associativity rule of the operator.You require all operators to have an associativity? Then what is the associativity of the operators for comparison?
May 01 2007
Bruno Medeiros wroteAll operands are evaluated left to right, with the exception of the assignment operators which are evaluated right-to-left.[...]Any problem with this one?Don't you see a reason why Walter has tossed himself out of this thread? Given an expression `a op b' | The expression is rewritten as both: | a.opfunc(b) | b.opfunc_r(a) This is from the specs! Now what is the evaluation order of `a op b'? `a' then `b'? `b' then `a'? If there is a cloud some people only see the silver lining. -manfred
May 01 2007
Manfred Nowak wrote:If there is a cloud some people only see the silver lining.That's a great phrase! I'm stealing it for my own purposes :-) Thanks! --benji
May 01 2007
Manfred Nowak wrote:Bruno Medeiros wroteHum, good point. This looks like an unprecedented case, I don't know if any other languages have reverse operator overloading like D. In any case a design decision would have to be made (thus creating a new evaluation rule). I would say that the order should be 'a' then 'b', because this way the programmer doesn't have to check which operator function is being invoked to know the evaluation order of such expression. This makes the code less dependent, which is particularly important since the underlying operator function could change in time, (from a non-reverse, to a reverse one, for example), and it would be best to maintain the original order semantics. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DAll operands are evaluated left to right, with the exception of the assignment operators which are evaluated right-to-left.[...]Any problem with this one?Don't you see a reason why Walter has tossed himself out of this thread? Given an expression `a op b' | The expression is rewritten as both: | a.opfunc(b) | b.opfunc_r(a) This is from the specs! Now what is the evaluation order of `a op b'? `a' then `b'? `b' then `a'? If there is a cloud some people only see the silver lining. -manfred
May 06 2007
Bruno Medeiros wrote:Hum, good point. This looks like an unprecedented case, I don't know if any other languages have reverse operator overloading like D.Rubbish. Python does as well, and for precisely the same reason I suspect D does: non-commutative operations, and working with existing, closed types. For instance, if you have a pre-existing, closed vector class, and you want to write a matrix class that works with it, you need to overload both opMul and opMul_r, or it won't work. I'd argue that any language that *doesn't* let you write the reverse operation is doing a pretty half-arsed job of operator overloading... Hell, I wrote vector and matrix structs from scratch, and I did it that way since having two templates depend on each other causes MORE than enough problems... I'm not entirely sure I fixed the data corruption issue it was causing, and I'd really rather not wrangle with that again. -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 06 2007
Bruno Medeiros wroteIn any case a design decision would have to be madeThere is at least one more such decision to be made. But what are they worth when it is anticipated, that the hardware will be able to evaluate complex expressions if there are no evaluation orders to be followed. -manfred
May 07 2007
Manfred Nowak wrote:Walter Bright wroteI agree. Furthermore, I strongly think it should be left as is. Why, because when I comeup against weird code like that, I don't want to have to consult the spec. Its like implicit casting, if you don't know what is happening your going to have a terrible time figuring out what is happening. This is one area where I think D could do a lot more to help the programmer avoid mistakes. Furthermore if its difficult to implement, you've just made D harder for someone else to implement. Please reconsider putting this in. -Joelit isn't easy to doIf it is not easy to define the order for the specs, then it will not be easy to learn, then near to nobody will know of or rely on the definition in the specs. Remember that even M$ recommends to fully parenthese expressions <because others might not know how to evaluate expressions without parentheses>. You once said, that you want to prohibit the upcoming of D-guru's. But if you yourself are not able to immediately sketch such order here, then you have the proof of upcoming gurus. If it is not easy to code then above arguments holds for compiler writers too. -manfred
Apr 26 2007
I tend to think if it's ambiguous it shouldn't be allowed. I most definitely do not want to be consulting an operator precedence chart every time I try to read other people's code. I personally think that shit like: for(i=0;i<x.length;){ if(i+=++i+3){ x[i][--i]; continue; } i++; } is starting to get really really bad... I wouldn't want to ever see 2000 lines of that shit.
Apr 28 2007