digitalmars.D.learn - An old topic (pun intended)
- Davidson Corry (20/20) Oct 12 2011 Did D2 ever implement the Eiffel "old" construct? I do not see it
- bearophile (9/11) Oct 13 2011 In classes inside a debug I have defined handmade "ghost attributes":
- Jonathan M Davis (5/14) Oct 13 2011 I don't recall him ever saying anything about contract programming in D ...
- Ali =?iso-8859-1?q?=C7ehreli?= (6/23) Oct 13 2011 He had mentioned that at some point the implementation of contract
- Timon Gehr (2/22) Oct 16 2011 Why would that be required?
- Ali =?iso-8859-1?q?=C7ehreli?= (7/17) Oct 17 2011 I am not sure myself. I find this thread where Andrei says "Walter tried...
- bearophile (8/14) Oct 13 2011 It add some complexity, but I can't agree that it adds little value, thi...
- Jonathan M Davis (5/17) Oct 13 2011 I'd have to go digging, but from what I recall, it was pretty clear that...
- bearophile (4/6) Oct 13 2011 I see. And sorry for the tone of my last answer. Don't worry if you don'...
- Davidson Corry (25/30) Oct 13 2011 Implementing DbC is tricky, and 'old' particularly so. For instance,
- Timon Gehr (7/48) Oct 16 2011 I don't agree that 'old' is very difficult to implement. Just evaluate
- Jonathan M Davis (5/12) Oct 16 2011 What if you're dealing with a class? You'd need to deep copy the entire ...
- Timon Gehr (6/18) Oct 16 2011 Eiffel does not do that either.
- bearophile (5/11) Oct 16 2011 I agree. A shallow prestate is quite better than not having it at all in...
- =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= (7/18) Oct 16 2011 Just for the record, the documentation is at:
- Davidson Corry (7/31) Oct 16 2011 Remember, efficiency is not the point, correctness is. Contract code
- =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= (5/41) Oct 17 2011 Right, but you don't want your debug builds to be so slow that it makes
- Jonathan M Davis (8/32) Oct 16 2011 I don't see how you could really expect to test the current state agains...
- Timon Gehr (27/60) Oct 17 2011 There are practical examples where this would be required but most of
Did D2 ever implement the Eiffel "old" construct? I do not see it mentioned in "The D Programming Language", and the only reference I can find in the newsgroup is a short discussion in June of 2007 that seemed to go nowhere. If not, has anyone developed a reasonable workaround? Thanks. -- Davidson ============ Brief description: in Eiffel, old expr can be used in post-conditions, and evaluates to the value of expr as of entry to the function. It's useful to help verify that the function has done what it was supposed to, but especially powerful when used in classes because it complements invariant: invariant tests what has *not* varied (duh), old expr helps test what *has* varied to ensure that it has varied *correctly*. For example, the .Add() method of a Container class might in its postcondition assert assert( count == old count + 1 ) to ensure that *exactly* one element got added, no more and no less
Oct 12 2011
Davidson Corry:Did D2 ever implement the Eiffel "old" construct?At the moment there no prestate in D. I agree that prestate is an important sub-feature of contract programming. It was discussed two or three times, but the discussions didn't produce actual results. I think it was not implemented because I think Walter thinks D contract programming is a half failure (I don't agree on this) and because implementing the prestate is a bit tricky. I suggest to ask about this in the main D newsgroup, and show two use cases too. I think if enough people show use cases, and someone writes a good enough pull request for DMD, it will be added to D/DMD.If not, has anyone developed a reasonable workaround? Thanks.In classes inside a debug I have defined handmade "ghost attributes": debug { int ghost1, ghost2; } I use them to manually store the prestate that later I want to verify. This is not a very good solution... Bye, bearophile
Oct 13 2011
On Thursday, October 13, 2011 05:35:52 bearophile wrote:Davidson Corry:I don't recall him ever saying anything about contract programming in D being a failure in any way. IIRC, old was rejected because it added extra complication for little value. - Jonathan M DavisDid D2 ever implement the Eiffel "old" construct?At the moment there no prestate in D. I agree that prestate is an important sub-feature of contract programming. It was discussed two or three times, but the discussions didn't produce actual results. I think it was not implemented because I think Walter thinks D contract programming is a half failure (I don't agree on this) and because implementing the prestate is a bit tricky.
Oct 13 2011
On Thu, 13 Oct 2011 09:18:46 -0700, Jonathan M Davis wrote:On Thursday, October 13, 2011 05:35:52 bearophile wrote:He had mentioned that at some point the implementation of contract programming had serious bugs but nobody had complained.Davidson Corry:I don't recall him ever saying anything about contract programming in D being a failure in any way.Did D2 ever implement the Eiffel "old" construct?At the moment there no prestate in D. I agree that prestate is an important sub-feature of contract programming. It was discussed two or three times, but the discussions didn't produce actual results. I think it was not implemented because I think Walter thinks D contract programming is a half failure (I don't agree on this) and because implementing the prestate is a bit tricky.IIRC, old was rejected because it added extra complication for little value.Yes, there were technical difficulties in making the stack frame at the call point available to the stack frame at the exit point.- Jonathan M DavisAli
Oct 13 2011
On 10/13/2011 07:14 PM, Ali Çehreli wrote:On Thu, 13 Oct 2011 09:18:46 -0700, Jonathan M Davis wrote:Why would that be required?On Thursday, October 13, 2011 05:35:52 bearophile wrote:He had mentioned that at some point the implementation of contract programming had serious bugs but nobody had complained.Davidson Corry:I don't recall him ever saying anything about contract programming in D being a failure in any way.Did D2 ever implement the Eiffel "old" construct?At the moment there no prestate in D. I agree that prestate is an important sub-feature of contract programming. It was discussed two or three times, but the discussions didn't produce actual results. I think it was not implemented because I think Walter thinks D contract programming is a half failure (I don't agree on this) and because implementing the prestate is a bit tricky.IIRC, old was rejected because it added extra complication for little value.Yes, there were technical difficulties in making the stack frame at the call point available to the stack frame at the exit point.
Oct 16 2011
On Sun, 16 Oct 2011 19:09:46 +0200, Timon Gehr wrote:On 10/13/2011 07:14 PM, Ali Çehreli wrote:I am not sure myself. I find this thread where Andrei says "Walter tried to implement that but it turned out to be very difficult implementation- wise": http://www.digitalmars.com/d/archives/digitalmars/D/ Communicating_between_in_and_out_contracts_98252.html AliOn Thu, 13 Oct 2011 09:18:46 -0700, Jonathan M Davis wrote:Why would that be required?IIRC, old was rejected because it added extra complication for little value.Yes, there were technical difficulties in making the stack frame at the call point available to the stack frame at the exit point.
Oct 17 2011
Jonathan M Davis:I don't recall him ever saying anything about contract programming in D being a failure in any way.He said unittesting has changed the why you write code and has significantly decreased bugs count, while he was not equally happy about contract programming. From several things he has said, he looks disappointed by D contract programming.IIRC, old was rejected because it added extra complication for little value.It add some complexity, but I can't agree that it adds little value, this is a mistake. The prestate increases significantly the usefulness of contract programming. And I don't remember it being rejected, I just remember the discussion stopped, like a river dying and drying up in a desert. Do you have a link of a post where it was rejected? I think there is an enhancement request about prestate in Bugzilla, and it is open still. Before actually rejecting this feature, it will need one more good discussion in the main D newsgroup. ---------------------- Ali Çehreli:He had mentioned that at some point the implementation of contract programming had serious bugs but nobody had complained.I am not sure, but I think I did complain about some of those bugs. I have some old bug reports in Bugzilla about contract programming that are open still. Bye, bearophile
Oct 13 2011
On Thursday, October 13, 2011 10:57 bearophile wrote:Jonathan M Davis:I'd have to go digging, but from what I recall, it was pretty clear that it wasn't happening. But since it's not a feature that I care about at all, it's not something that I've tracked particularly closely. - Jonathan M DavisIIRC, old was rejected because it added extra complication for little value.It add some complexity, but I can't agree that it adds little value, this is a mistake. The prestate increases significantly the usefulness of contract programming. And I don't remember it being rejected, I just remember the discussion stopped, like a river dying and drying up in a desert. Do you have a link of a post where it was rejected? I think there is an enhancement request about prestate in Bugzilla, and it is open still. Before actually rejecting this feature, it will need one more good discussion in the main D newsgroup.
Oct 13 2011
Jonathan M Davis:I'd have to go digging, but from what I recall, it was pretty clear that it wasn't happening.I see. And sorry for the tone of my last answer. Don't worry if you don't have the time to find it. Bye, bearophile
Oct 13 2011
On 10/13/2011 10:57 AM, bearophile wrote:Jonathan M Davis:Implementing DbC is tricky, and 'old' particularly so. For instance, what if the condition whose state-at-entry you want to inspect at exit happens to reside in a base class implemented in a different module? (Note that D supports separate compilation while Eiffel doesn't.) 'unittest' is a major win in D, and may as a practical matter alleviate much of the need for other kinds of testing. But... [opinion] ...unit testing and DbC are *orthogonal* or at least complementary, in my view. Conceptually, unit testing tests a class or object from the *outside* of its public boundaries, while DbC tests the object from *within*. They catch different classes (sic) of implementation error. Some bugs may be caught both ways, which is great. But some might slip by one, only to be caught by the other. Like any technique (including unit testing) DbC takes practice to learn how to do well, and it is new to most programmers even 25 years after Meyer brought it to the masses. There's a bootstrapping problem here: if DbC isn't fully implemented, it's not as useful. If it's not useful, programmers won't use it. If they don't use it, compiler implementers won't improve the implementation. And so on. Look, Walters are in scarce supply, and I don't want to jog their elbows on priorities -- they come up with so much other cool stuff! I'm just saying, 'old' would be nice. [/opinion] -- DavidsonI don't recall him ever saying anything about contract programming in D being a failure in any way.He said unittesting has changed the way you write code and has significantly decreased bugs count, while he was not equally happy about contract programming. From several things he has said, he looks disappointed by D contract programming.IIRC, old was rejected because it added extra complication for little value.It add some complexity, but I can't agree that it adds little value... And I don't remember it being rejected, I just remember the discussion stopped, like a river dying and drying up in a desert.
Oct 13 2011
On 10/13/2011 08:25 PM, Davidson Corry wrote:On 10/13/2011 10:57 AM, bearophile wrote:I don't agree that 'old' is very difficult to implement. Just evaluate what is inside the 'old' before you enter the in contract, store somewhere, maybe in hidden local variables, and make the data available in the out contract. Eiffel's 'old' does not do more than that. (but perhaps there are implementation details in DMD that make this more difficult than necessary. I don't know.)Jonathan M Davis:Implementing DbC is tricky, and 'old' particularly so. For instance, what if the condition whose state-at-entry you want to inspect at exit happens to reside in a base class implemented in a different module? (Note that D supports separate compilation while Eiffel doesn't.) 'unittest' is a major win in D, and may as a practical matter alleviate much of the need for other kinds of testing. But... [opinion] ...unit testing and DbC are *orthogonal* or at least complementary, in my view. Conceptually, unit testing tests a class or object from the *outside* of its public boundaries, while DbC tests the object from *within*. They catch different classes (sic) of implementation error. Some bugs may be caught both ways, which is great. But some might slip by one, only to be caught by the other. Like any technique (including unit testing) DbC takes practice to learn how to do well, and it is new to most programmers even 25 years after Meyer brought it to the masses. There's a bootstrapping problem here: if DbC isn't fully implemented, it's not as useful. If it's not useful, programmers won't use it. If they don't use it, compiler implementers won't improve the implementation. And so on. Look, Walters are in scarce supply, and I don't want to jog their elbows on priorities -- they come up with so much other cool stuff! I'm just saying, 'old' would be nice. [/opinion] -- DavidsonI don't recall him ever saying anything about contract programming in D being a failure in any way.He said unittesting has changed the way you write code and has significantly decreased bugs count, while he was not equally happy about contract programming. From several things he has said, he looks disappointed by D contract programming.IIRC, old was rejected because it added extra complication for little value.It add some complexity, but I can't agree that it adds little value... And I don't remember it being rejected, I just remember the discussion stopped, like a river dying and drying up in a desert.
Oct 16 2011
On Sunday, October 16, 2011 19:13:09 Timon Gehr wrote:I don't agree that 'old' is very difficult to implement. Just evaluate what is inside the 'old' before you enter the in contract, store somewhere, maybe in hidden local variables, and make the data available in the out contract. Eiffel's 'old' does not do more than that. (but perhaps there are implementation details in DMD that make this more difficult than necessary. I don't know.)What if you're dealing with a class? You'd need to deep copy the entire object for it to work. There's no way built into the language to do that (not to mention that it would be horrifically inefficient). - Jonathan M Davis
Oct 16 2011
On 10/16/2011 07:31 PM, Jonathan M Davis wrote:On Sunday, October 16, 2011 19:13:09 Timon Gehr wrote:Eiffel does not do that either. (even though it _does_ have a built in deep copy feature) We don't have to over-engineer the feature, if somebody needs to deep-copy an object they can implement it themselves and use old(obj.deepCopy()).I don't agree that 'old' is very difficult to implement. Just evaluate what is inside the 'old' before you enter the in contract, store somewhere, maybe in hidden local variables, and make the data available in the out contract. Eiffel's 'old' does not do more than that. (but perhaps there are implementation details in DMD that make this more difficult than necessary. I don't know.)What if you're dealing with a class? You'd need to deep copy the entire object for it to work. There's no way built into the language to do that (not to mention that it would be horrifically inefficient). - Jonathan M Davis
Oct 16 2011
Timon Gehr:Eiffel does not do that either. (even though it _does_ have a built in deep copy feature) We don't have to over-engineer the feature, if somebody needs to deep-copy an object they can implement it themselves and use old(obj.deepCopy()).I agree. A shallow prestate is quite better than not having it at all in D. taking a look. Bye, bearophile
Oct 16 2011
On 17-10-2011 02:43, bearophile wrote:Timon Gehr:Just for the record, the documentation is at: http://download.microsoft.com/download/C/2/7/C2715F76-F56C-4D37-9231-EF8076B7EC13/userdoc.pdf I agree that having old would be great, even if without deep copying deep copying here. - AlexEiffel does not do that either. (even though it _does_ have a built in deep copy feature) We don't have to over-engineer the feature, if somebody needs to deep-copy an object they can implement it themselves and use old(obj.deepCopy()).I agree. A shallow prestate is quite better than not having it at all in D. taking a look. Bye, bearophile
Oct 16 2011
On 10/16/2011 9:35 PM, Alex Rønne Petersen wrote:On 17-10-2011 02:43, bearophile wrote:Remember, efficiency is not the point, correctness is. Contract code goes away in the release build. (Arguably you might want to keep *preconditions* in library code, since they vet your input parameters. But in practice those usually go away in release builds as well, even in Eiffel.) -- DaiTimon Gehr:Just for the record, the documentation is at: http://download.microsoft.com/download/C/2/7/C2715F76-F56C-4D37-9231-EF8076B7EC13/userdoc.pdf I agree that having old would be great, even if without deep copying deep copying here. - AlexEiffel does not do that either. (even though it _does_ have a built in deep copy feature) We don't have to over-engineer the feature, if somebody needs to deep-copy an object they can implement it themselves and use old(obj.deepCopy()).I agree. A shallow prestate is quite better than not having it at all in D. it's worth taking a look. Bye, bearophile
Oct 16 2011
On 17-10-2011 07:59, Davidson Corry wrote:On 10/16/2011 9:35 PM, Alex Rønne Petersen wrote:Right, but you don't want your debug builds to be so slow that it makes you unproductive either. Either way, an initial lightweight old() would already be much better than having nothing. :) - AlexOn 17-10-2011 02:43, bearophile wrote:Remember, efficiency is not the point, correctness is. Contract code goes away in the release build. (Arguably you might want to keep *preconditions* in library code, since they vet your input parameters. But in practice those usually go away in release builds as well, even in Eiffel.) -- DaiTimon Gehr:Just for the record, the documentation is at: http://download.microsoft.com/download/C/2/7/C2715F76-F56C-4D37-9231-EF8076B7EC13/userdoc.pdf I agree that having old would be great, even if without deep copying deep copying here. - AlexEiffel does not do that either. (even though it _does_ have a built in deep copy feature) We don't have to over-engineer the feature, if somebody needs to deep-copy an object they can implement it themselves and use old(obj.deepCopy()).I agree. A shallow prestate is quite better than not having it at all in D. it's worth taking a look. Bye, bearophile
Oct 17 2011
On Monday, October 17, 2011 00:29:30 Timon Gehr wrote:On 10/16/2011 07:31 PM, Jonathan M Davis wrote:I don't see how you could really expect to test the current state against the initial state when you don't actually save the initial state. And as far as implementing it yourself goes, you could go and do that that right now. You don't need compiler support to save the initial state somewhere and then test against it afterwards. It's just nicer if the compiler gives you support for it. - Jonathan M DavisOn Sunday, October 16, 2011 19:13:09 Timon Gehr wrote:Eiffel does not do that either. (even though it _does_ have a built in deep copy feature) We don't have to over-engineer the feature, if somebody needs to deep-copy an object they can implement it themselves and use old(obj.deepCopy()).I don't agree that 'old' is very difficult to implement. Just evaluate what is inside the 'old' before you enter the in contract, store somewhere, maybe in hidden local variables, and make the data available in the out contract. Eiffel's 'old' does not do more than that. (but perhaps there are implementation details in DMD that make this more difficult than necessary. I don't know.)What if you're dealing with a class? You'd need to deep copy the entire object for it to work. There's no way built into the language to do that (not to mention that it would be horrifically inefficient). - Jonathan M Davis
Oct 16 2011
On 10/17/2011 08:04 AM, Jonathan M Davis wrote:On Monday, October 17, 2011 00:29:30 Timon Gehr wrote:There are practical examples where this would be required but most of the time the tests are simple enough that the old expression can carry all the state you need. Remember that all implementations of DbC that have prestate (and I am aware of) don't perform a deep copy automatically. Eg: abstract class Set{ property int size(); bool contains(int x); void insert(int x) out{ assert( old(contains(x)) && size == old(size) || !old(contains(x)) && size == old(size)+1); assert(contains(old(x))); // possibly also require that everything that was // in the set before is still there [...] } }On 10/16/2011 07:31 PM, Jonathan M Davis wrote:I don't see how you could really expect to test the current state against the initial state when you don't actually save the initial state.On Sunday, October 16, 2011 19:13:09 Timon Gehr wrote:Eiffel does not do that either. (even though it _does_ have a built in deep copy feature) We don't have to over-engineer the feature, if somebody needs to deep-copy an object they can implement it themselves and use old(obj.deepCopy()).I don't agree that 'old' is very difficult to implement. Just evaluate what is inside the 'old' before you enter the in contract, store somewhere, maybe in hidden local variables, and make the data available in the out contract. Eiffel's 'old' does not do more than that. (but perhaps there are implementation details in DMD that make this more difficult than necessary. I don't know.)What if you're dealing with a class? You'd need to deep copy the entire object for it to work. There's no way built into the language to do that (not to mention that it would be horrifically inefficient). - Jonathan M DavisAnd as far as implementing it yourself goes, you could go and do that that right now. You don't need compiler support to save the initial state somewhere and then test against it afterwards. It's just nicer if the compiler gives you support for it. - Jonathan M DavisAs far as implementing it myself goes I could even do contract programming in the brainF programming language. =) The feature adds a lot of value to contract programming. I use contract programming occasionally and almost every contract I add eventually detects small bugs during the testing of new code parts. BTW: "Somewhere" would have to be on the execution stack because the function could be recursive. There is no way to refer to variables defined in the in contract from the out contract and doing the saving at any other place than in a contract is not acceptable for obvious reasons.
Oct 17 2011