digitalmars.D - Another idiom I wish were gone from phobos/druntime
- Andrei Alexandrescu (26/26) Feb 04 2015 I'm seeing another idiom that seems to become fashionable. Consider this...
- Rikki Cattermole (5/31) Feb 04 2015 So are we recommending against contract based programming for simple
- Andrei Alexandrescu (4/8) Feb 04 2015 That would be a separate discussion.
- bearophile (6/25) Feb 04 2015 Contracts can be read by tools, and they are part of the function
- Adam D. Ruppe (6/9) Feb 04 2015 I agree. Moreover, if the assert fails in the contract, in
- Andrei Alexandrescu (4/12) Feb 04 2015 Yah I concede this is a good point. Yet we're looking at an actual
- deadalnix (4/7) Feb 04 2015 There only a benefit because the coding style for contract is
- Zach the Mystic (8/28) Feb 04 2015 I have an idea. Treat all assert statements which come before the
- bearophile (4/10) Feb 04 2015 Bad idea. We had DbC, let's start using it.
- Zach the Mystic (3/13) Feb 05 2015 My proposal is just effectively syntax sugar for DbC, which the
- deadalnix (5/11) Feb 04 2015 No. There is no point of screwing up the language because an
- Zach the Mystic (20/31) Feb 05 2015 Screwing up the language? I'd be willing to accept your position
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (4/7) Feb 08 2015 Daniel Murphy has (function stubs with `assert(0)`), here:
- Zach the Mystic (29/36) Feb 08 2015 assert(0) is a special case, and could be easily identified as
- Daniel Murphy (23/33) Feb 08 2015 Here's one:
- Zach the Mystic (16/52) Feb 08 2015 Well, okay. This is a case where there is a slight practical
- ketmar (6/22) Feb 05 2015 wait, do you mean that there was paradigm shift and we will no more keep...
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (8/17) Feb 08 2015 FWIW (only reading this discussion now, sorry if it has already
- Tobias Pankrath (6/18) Feb 04 2015 auto opSlice(size_t low, size_t high)
- Jonathan Marler (6/11) Feb 04 2015 Not to mention that contracts can be removed by the compiler at
- Andrei Alexandrescu (2/10) Feb 04 2015 Same about asserts. -- Andrei
- deadalnix (6/20) Feb 04 2015 assert run in the callee, in contract SHOULD (but currently
- Jonathan Marler (16/30) Feb 04 2015 Only if the function is inlined. The function variables are
- Andrei Alexandrescu (2/17) Feb 04 2015 Non-debug mode removes asserts statically. -- Andrei
- David Nadlinger (6/7) Feb 04 2015 Using pre-/post-conditions allows the _caller_ to specify whether
- Jonathan M Davis via Digitalmars-d (27/33) Feb 05 2015 In theory, yes. And then in blocks would provide some value outside of
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (13/18) Feb 05 2015 You could have an IDE and build system that makes signatures,
- deadalnix (3/19) Feb 05 2015 DMD is broken. There is no need to break phobos in addition.
- Dragos Carp (8/30) Feb 05 2015 This is correct only if non-debug mode means -release flag
- Andrei Alexandrescu (3/5) Feb 04 2015 The signature part matters only for overridable functions. I agree the
- deadalnix (18/45) Feb 04 2015 Various things.
- Andrei Alexandrescu (7/18) Feb 04 2015 Would introduce an exception to our brace-on-its-line rule.
- Jonathan Marler (17/30) Feb 04 2015 My definition of an in contract is a condition that the caller is
- deadalnix (11/13) Feb 04 2015 Putting the contract in the caller is not only useful for
- Andrei Alexandrescu (3/16) Feb 04 2015 Yah, I understand the potential there. Consider me grudgingly convinced
- Meta (12/39) Feb 04 2015 I don't know about others (besides Beatophile, who religiously
- H. S. Teoh via Digitalmars-d (14/23) Feb 04 2015 I do write contracts in my own code, though not as much as I would've
- Meta (6/42) Feb 04 2015 I've found that the more years of experience I have under my
- Vlad Levenfeld (23/28) Feb 04 2015 $0.02:
- Vlad Levenfeld (4/5) Feb 04 2015 Er, stupid but unfortunately common american english idiom. For
- eles (3/7) Feb 05 2015 Thanks. I was firmly convinced that's a typo...
- Jonathan M Davis via Digitalmars-d (5/13) Feb 05 2015 No. It's just a frustratingly common mistake - like saying "for all
- Vlad Levenfeld (5/10) Feb 05 2015 Well, when you grow up hearing it, you reach for the notion and
- Mike Parker (2/16) Feb 05 2015 I can't phantom that!
- Andrei Alexandrescu (2/21) Feb 05 2015 I think we should return to the topic at hand irregardless. -- Andrei
- Walter Bright (2/4) Feb 05 2015 What? I thought it was "for all infants and porpoises"!
- H. S. Teoh via Digitalmars-d (7/12) Feb 05 2015 What, what? For elephants and porpoises? I thought this was a
- Jonathan M Davis via Digitalmars-d (3/7) Feb 05 2015 LOL.
- Paulo Pinto (5/41) Feb 04 2015 I miss the point about in.
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (34/38) Feb 04 2015 Conceptually the precondition is a specification that the caller
- deadalnix (6/10) Feb 05 2015 There was a huge discussion here:
- Paulo Pinto (7/19) Feb 05 2015 So the caller can break the contract without any consideration
- deadalnix (2/6) Feb 05 2015 Yes, it is called cargo cult.
- Paulo Pinto (2/11) Feb 05 2015 I am out.
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (7/19) Feb 05 2015 Out of the rabbit hole, like Alice in Wonderland?
- Paulo Pinto (12/33) Feb 05 2015 I believe the Eiffel way, just like the industry does, with
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (58/61) Feb 05 2015 I believe Ada allows the separation of interface and
- bearophile (6/56) Feb 06 2015 That seems a bit too much for the average human to handle :-)
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (28/31) Feb 06 2015 So D has to decide what development scenario it wants to compete
- deadalnix (3/15) Feb 05 2015 To be frankly brutal, you were never in. You presented no
- Paulo Pinto (22/39) Feb 05 2015 I did, by stating that the way Eiffel does is how it is supposed
- Andrei Alexandrescu (3/4) Feb 05 2015 That issue reveals that Eiffel essentially contradicts directly its
- deadalnix (16/23) Feb 05 2015 In the links that were provided to you, you'll see one instance
- eles (2/11) Feb 05 2015 Wow. Amazing discussion.
- eles (5/18) Feb 05 2015 But it ends with:
- Daniel Murphy (3/7) Feb 05 2015 I don't speak for Walter, but I expect if it can be implemented in a san...
- Andrei Alexandrescu (2/20) Feb 05 2015 It has been preapproved. The challenge now is implementing it. -- Andrei
- Andrei Alexandrescu (3/26) Feb 05 2015 Better put: it had been preapproved back in Jan 2013 and is still
- Daniel Murphy (6/14) Feb 04 2015 Would you be more likely to write contracts if something like this was
- Meta (10/27) Feb 05 2015 I have seen that PR previously, and I do hope it gets merged. It
- Daniel Murphy (4/12) Feb 05 2015 Yes, optimization is another nice possibility. I think there is a lot o...
- Andrei Alexandrescu (4/7) Feb 05 2015 I agree. One actionable - albeit crazy :o) - idea is to make __FILE__,
- Daniel Murphy (6/9) Feb 05 2015 Unfortunately that's not practical until contracts have been changed to ...
- Jonathan M Davis via Digitalmars-d (39/53) Feb 05 2015 If the semantics of
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (6/12) Feb 05 2015 The difference is that implementation asserts() are part of
- Jonathan M Davis via Digitalmars-d (34/46) Feb 05 2015 There is no such difference in the current implementation. assertions in...
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (35/72) Feb 05 2015 But that is a compiler issue, and not a general issue with
- Kagamin (6/12) Feb 05 2015 Good point. One problem is that base asserts throw exceptions on
- Jonathan M Davis via Digitalmars-d (7/19) Feb 05 2015 Virtual functions is the _one_ place where using in and out blocks actua...
- Daniel Murphy (24/41) Feb 05 2015 Yes, and we are almost certainly going to change it so that the caller's...
- Jonathan M Davis via Digitalmars-d (10/22) Feb 05 2015 Well, if we can change it so that whether the contracts are run or not i...
- Daniel Murphy (5/17) Feb 05 2015 I agree, and that's a big part of why I opened that pull request. The i...
- Atila Neves (9/49) Feb 05 2015 I also make all my variables immutable unless I can't. Which is
- Walter Bright (3/15) Feb 05 2015 I was prepared to argue with you, but you're right on all points. Nicely...
- deadalnix (5/6) Feb 04 2015 Will I start the next world war if I mention this rule is only
- H. S. Teoh via Digitalmars-d (7/11) Feb 04 2015 It's an example of blindly adhering to the letter of the rule while
- Jonathan Marler (3/8) Feb 04 2015 Ahhh...thanks for this. I've been searching for an eloquent way
- Andrei Alexandrescu (3/11) Feb 04 2015 Hey, I've been saying that all over
- Nick Treleaven (3/7) Feb 05 2015 We really should support => syntax for these instead, they are very
- Andrei Alexandrescu (3/8) Feb 04 2015 As a Facebook fellow, I wouldn't mind Egyptian braces. But they won't
- Kagamin (11/18) Feb 05 2015 If contracts would support single statements:
- Nick Treleaven (13/21) Feb 05 2015 +1, but with the statements in the function body please:
- H. S. Teoh via Digitalmars-d (28/50) Feb 04 2015 I disagree.
- Jonathan M Davis via Digitalmars-d (21/46) Feb 05 2015 As far as I can tell, there is zero reason to use in blocks aside from w...
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (11/19) Feb 05 2015 That would be true if:
- Jonathan M Davis via Digitalmars-d (30/49) Feb 05 2015 If you're not doing exhaustive unit testing, you're almost certainly doi...
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (44/75) Feb 05 2015 That would be a NP-Hard problem for any function that takes an
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (3/5) Feb 05 2015 Duh, that was wrong... It is only IF, not IFF...
- ketmar (4/32) Feb 05 2015 so you basically telling that "in block" feature is so useless, that eve...
- Chris (23/50) Feb 06 2015 [caveat: I've read some of the posts, yet I don't know, if this
- ketmar (3/7) Feb 06 2015 dead before the start.=
- Chris (2/9) Feb 06 2015 Why? Would you mind to elaborate on that a little? ;)
I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407: auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low <= high); import std.range : take; return this[low .. $].take(high - low); } What advantage could possibly be in transforming a 5-liner into a 9-liner? Are we really aiming at writing the maximum possible lines of code here and using as many language features as possible everywhere? I think we should dust off that Phobos contributors' guide. Sadly, there is little we can do against the more subtle issues. Andrei
Feb 04 2015
On 5/02/2015 1:24 p.m., Andrei Alexandrescu wrote:I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407: auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low <= high); import std.range : take; return this[low .. $].take(high - low); } What advantage could possibly be in transforming a 5-liner into a 9-liner? Are we really aiming at writing the maximum possible lines of code here and using as many language features as possible everywhere? I think we should dust off that Phobos contributors' guide. Sadly, there is little we can do against the more subtle issues. AndreiSo are we recommending against contract based programming for simple getter type methods? Personally I think those auto's are more important to get rid of in this code. They actually do harm for anyone reading the docs.
Feb 04 2015
On 2/4/15 4:30 PM, Rikki Cattermole wrote:So are we recommending against contract based programming for simple getter type methods?The shorter version is as contract based as the other.Personally I think those auto's are more important to get rid of in this code. They actually do harm for anyone reading the docs.That would be a separate discussion. Andrei
Feb 04 2015
Andrei Alexandrescu:auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low <= high); import std.range : take; return this[low .. $].take(high - low); } What advantage could possibly be in transforming a 5-liner into a 9-liner?Contracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophile
Feb 04 2015
On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Contracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged.I agree. Moreover, if the assert fails in the contract, in theory, we can point the error at the user's code. An assert inside the function is the function's responsibility. An assert in an in contract is the caller's responsibility. They're semantically different (even if dmd treats them the same way)
Feb 04 2015
On 2/4/15 4:37 PM, Adam D. Ruppe wrote:On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Yah I concede this is a good point. Yet we're looking at an actual liability and are supposed to look at some vague possible future benefit. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged.I agree. Moreover, if the assert fails in the contract, in theory, we can point the error at the user's code. An assert inside the function is the function's responsibility. An assert in an in contract is the caller's responsibility. They're semantically different (even if dmd treats them the same way)
Feb 04 2015
On Thursday, 5 February 2015 at 00:43:04 UTC, Andrei Alexandrescu wrote:Yah I concede this is a good point. Yet we're looking at an actual liability and are supposed to look at some vague possible future benefit. -- AndreiThere only a benefit because the coding style for contract is ridiculous. Let's fix the right problem here.
Feb 04 2015
On Thursday, 5 February 2015 at 00:43:04 UTC, Andrei Alexandrescu wrote:On 2/4/15 4:37 PM, Adam D. Ruppe wrote:I have an idea. Treat all assert statements which come before the first non-assert statement as part of the 'in' contract. I'm not saying the compiler has to generate a whole 'in' function, but these asserts can be internally tagged to behave *as if* in an 'in' contract. That solves the tooling problem and the too-much-code problem, no?On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Yah I concede this is a good point. Yet we're looking at an actual liability and are supposed to look at some vague possible future benefit. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged.I agree. Moreover, if the assert fails in the contract, in theory, we can point the error at the user's code. An assert inside the function is the function's responsibility. An assert in an in contract is the caller's responsibility. They're semantically different (even if dmd treats them the same way)
Feb 04 2015
Zach the Mystic:I have an idea. Treat all assert statements which come before the first non-assert statement as part of the 'in' contract. I'm not saying the compiler has to generate a whole 'in' function, but these asserts can be internally tagged to behave *as if* in an 'in' contract. That solves the tooling problem and the too-much-code problem, no?Bad idea. We had DbC, let's start using it. Bye, bearophile
Feb 04 2015
On Thursday, 5 February 2015 at 05:48:43 UTC, bearophile wrote:Zach the Mystic:My proposal is just effectively syntax sugar for DbC, which the average programmer (not you!) will actually want to use.I have an idea. Treat all assert statements which come before the first non-assert statement as part of the 'in' contract. I'm not saying the compiler has to generate a whole 'in' function, but these asserts can be internally tagged to behave *as if* in an 'in' contract. That solves the tooling problem and the too-much-code problem, no?Bad idea. We had DbC, let's start using it. Bye, bearophile
Feb 05 2015
On Thursday, 5 February 2015 at 04:36:39 UTC, Zach the Mystic wrote:I have an idea. Treat all assert statements which come before the first non-assert statement as part of the 'in' contract. I'm not saying the compiler has to generate a whole 'in' function, but these asserts can be internally tagged to behave *as if* in an 'in' contract. That solves the tooling problem and the too-much-code problem, no?No. There is no point of screwing up the language because an arbitrary choice of formating is taking an absurd amount of vertical space.
Feb 04 2015
On Thursday, 5 February 2015 at 07:06:31 UTC, deadalnix wrote:On Thursday, 5 February 2015 at 04:36:39 UTC, Zach the Mystic wrote:Screwing up the language? I'd be willing to accept your position if I could think of any possible instance in which: T myFunc() assert(xxx); assert(yyy); doStuff(); } ... were not intended to be semantically equivalent to: T myFunc() in { assert(xxx); assert(yyy); } body { doStuff(); } Can you name one, or even imagine one? Bear in mind people like Andrei and myself do not like to read or write the later form and will use it much less, regardless of benefit.I have an idea. Treat all assert statements which come before the first non-assert statement as part of the 'in' contract. I'm not saying the compiler has to generate a whole 'in' function, but these asserts can be internally tagged to behave *as if* in an 'in' contract. That solves the tooling problem and the too-much-code problem, no?No. There is no point of screwing up the language because an arbitrary choice of formating is taking an absurd amount of vertical space.
Feb 05 2015
On Thursday, 5 February 2015 at 16:34:38 UTC, Zach the Mystic wrote:Can you name one, or even imagine one? Bear in mind people like Andrei and myself do not like to read or write the later form and will use it much less, regardless of benefit.Daniel Murphy has (function stubs with `assert(0)`), here: http://forum.dlang.org/thread/maud7e$1j3u$1 digitalmars.com?page=7#post-mavf13:24130j:241:40digitalmars.com
Feb 08 2015
On Sunday, 8 February 2015 at 13:03:28 UTC, Marc Schütz wrote:On Thursday, 5 February 2015 at 16:34:38 UTC, Zach the Mystic wrote:assert(0) is a special case, and could be easily identified as such. My attitude would be to try to find a way to make this work, according to the principle that the common case should be easy, and the rarer case possible. The difference only applies to what the user is told about when the assert fails, and not the execution semantics themselves - so it's really not "screwing up the language", unless I'm wrong. Also, in Daniel Murphy's example: void func(int x) in { assert(x > 6); // If this assert fails the caller was incorrect } body { assert(x > 7); // If this assert fails then 'func' has a bug. } I don't know how the second assert could men somethign different from the first. If you assert (anything but assert(0)) first thing, you certainly are not checking for bugs *within* the function - you're checking for entry conditions. So the question is whether the practical difference between the two asserts above is sufficient to prevent applying the syntax sugar. I personally can live with it either way (I can handle being told the the function failed when it was really the caller that failed), but it's a judgment call. I mean, this thread was literally called "Another idiom I wish were gone from phobos/druntime." I don't expect it is the last time someone will complain about it.Can you name one, or even imagine one? Bear in mind people like Andrei and myself do not like to read or write the later form and will use it much less, regardless of benefit.Daniel Murphy has (function stubs with `assert(0)`), here: http://forum.dlang.org/thread/maud7e$1j3u$1 digitalmars.com?page=7#post-mavf13:24130j:241:40digitalmars.com
Feb 08 2015
"Zach the Mystic" wrote in message news:qxtyqdeewrjurmwhksbj forum.dlang.org...I don't know how the second assert could men somethign different from the first. If you assert (anything but assert(0)) first thing, you certainly are not checking for bugs *within* the function - you're checking for entry conditions. So the question is whether the practical difference between the two asserts above is sufficient to prevent applying the syntax sugar. I personally can live with it either way (I can handle being told the the function failed when it was really the caller that failed), but it's a judgment call. I mean, this thread was literally called "Another idiom I wish were gone from phobos/druntime." I don't expect it is the last time someone will complain about it.Here's one: struct S { private: static int instanceCount; ... public: void func(int x) in { assert(x >= 0, "can't call func with negative x"); } body { assert(instanceCount > 0); } } The first assert checks something the caller has control over, the second assert is a sanity check, and if it fails it's not an error in the caller. Anyway, IMO there is zero chance of this making it into the language and you're wasting your energy.
Feb 08 2015
On Sunday, 8 February 2015 at 17:12:20 UTC, Daniel Murphy wrote:"Zach the Mystic" wrote in message news:qxtyqdeewrjurmwhksbj forum.dlang.org...Well, okay. This is a case where there is a slight practical difference. In the spirit of keeping the rare case possible, I would suggest: body { {} // reject in-contract assert assert(instanceCount > 0); }I don't know how the second assert could men somethign different from the first. If you assert (anything but assert(0)) first thing, you certainly are not checking for bugs *within* the function - you're checking for entry conditions. So the question is whether the practical difference between the two asserts above is sufficient to prevent applying the syntax sugar. I personally can live with it either way (I can handle being told the the function failed when it was really the caller that failed), but it's a judgment call. I mean, this thread was literally called "Another idiom I wish were gone from phobos/druntime." I don't expect it is the last time someone will complain about it.Here's one: struct S { private: static int instanceCount; ... public: void func(int x) in { assert(x >= 0, "can't call func with negative x"); } body { assert(instanceCount > 0); } } The first assert checks something the caller has control over, the second assert is a sanity check, and if it fails it's not an error in the caller.Anyway, IMO there is zero chance of this making it into the language and you're wasting your energy.That's disappointing, but I didn't waste my energy. I realized there's validity to both sides of this argument (bulky contracts vs. accurate errors), and instead of choosing a side, I tried to come up with the biggest total win for both sides. I think my solution is a 80-90% win for both sides, which is better than 100-0% for just one. If it gets rejected for some other reason, so be it. I'm trying to help, here!
Feb 08 2015
On Wed, 04 Feb 2015 16:43:04 -0800, Andrei Alexandrescu wrote:On 2/4/15 4:37 PM, Adam D. Ruppe wrote:wait, do you mean that there was paradigm shift and we will no more keep=20 shit in the language due to non-existent Jack The Random Reddit User told=20 that he used that shit once? does that mean that typle syntax PR will be=20 accepted, 'cause blocking it is a look at some vague possible future=20 benefit?=On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:=20 Yah I concede this is a good point. Yet we're looking at an actual liability and are supposed to look at some vague possible future benefit. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged.I agree. Moreover, if the assert fails in the contract, in theory, we can point the error at the user's code. An assert inside the function is the function's responsibility. An assert in an in contract is the caller's responsibility. They're semantically different (even if dmd treats them the same way)
Feb 05 2015
On Thursday, 5 February 2015 at 00:37:31 UTC, Adam D. Ruppe wrote:On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:FWIW (only reading this discussion now, sorry if it has already been stated by someone else), this was also talked about at the Berlin meeting, with the same conclusion. IIRC someone was disappointed that failure on the caller's side to pass correct parameters to a library with contracts caused AssertErrors to be thrown inside the callee, making it seem it was the library's fault.Contracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged.I agree. Moreover, if the assert fails in the contract, in theory, we can point the error at the user's code. An assert inside the function is the function's responsibility. An assert in an in contract is the caller's responsibility. They're semantically different (even if dmd treats them the same way)
Feb 08 2015
On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Andrei Alexandrescu:auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { }auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); }
Feb 04 2015
On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Contracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophileNot to mention that contracts can be removed by the compiler at compile time. i.e. x.opSlice(i, i+1); The assert can be compiled away since i+1 is always >= i. That's one of the great benefits of contracts.
Feb 04 2015
On 2/4/15 4:40 PM, Jonathan Marler wrote:On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Same about asserts. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophileNot to mention that contracts can be removed by the compiler at compile time.
Feb 04 2015
On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:On 2/4/15 4:40 PM, Jonathan Marler wrote:assert run in the callee, in contract SHOULD (but currently don't) run in the caller. That do not create the same optimization opportunities (unless inlining occurs, making the caller and the caller one).On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Same about asserts. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophileNot to mention that contracts can be removed by the compiler at compile time.
Feb 04 2015
On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:On 2/4/15 4:40 PM, Jonathan Marler wrote:Only if the function is inlined. The function variables are unknown at compile time so there's no way for the function to compile it away (unless the optimizer can see every single call to the function). If you make the caller responsible for the assert then it can determine whether or not it needs to perform it at runtime. Then what about chaining contracts. If a function has an out contract saying that the return value will be between a certain range, and you use that same variable in another function that requires it to be in the same range, you can compile away any assert after the first one. This is trivial to do with contracts. You could do it without contracts I suppose, but would be much more brittle (every single return location would have to have the same assert for example)On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Same about asserts. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophileNot to mention that contracts can be removed by the compiler at compile time.
Feb 04 2015
On 2/4/15 4:50 PM, Jonathan Marler wrote:On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:Non-debug mode removes asserts statically. -- AndreiOn 2/4/15 4:40 PM, Jonathan Marler wrote:Only if the function is inlined.On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Same about asserts. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophileNot to mention that contracts can be removed by the compiler at compile time.
Feb 04 2015
On Thursday, 5 February 2015 at 01:09:15 UTC, Andrei Alexandrescu wrote:Non-debug mode removes asserts statically. -- AndreiUsing pre-/post-conditions allows the _caller_ to specify whether the checks are run without recompiling the function body, at least in theory. David
Feb 04 2015
On Thursday, February 05, 2015 01:33:54 David Nadlinger via Digitalmars-d wrote:On Thursday, 5 February 2015 at 01:09:15 UTC, Andrei Alexandrescu wrote:In theory, yes. And then in blocks would provide some value outside of virtual functions. But as it stands, there is _zero_ semantic difference between void foo(int i) in { assert(i > 0); } body { ... } and void foo(int i) { assert(i > 0); ... } And unless we make some serious changes to how D functions are called, I don't see how it could possibly be otherwise. in and out blocks and invariants are not part of the function signature. They're implementation details that disappear when prototypes are used. So, while in principle, it would be great if assertions related to contracts were enabled or disabled by the caller, not only does it not work that way now, I have no idea how it even could work that way. - Jonathan M DavisNon-debug mode removes asserts statically. -- AndreiUsing pre-/post-conditions allows the _caller_ to specify whether the checks are run without recompiling the function body, at least in theory.
Feb 05 2015
On Thursday, 5 February 2015 at 08:05:30 UTC, Jonathan M Davis wrote:So, while in principle, it would be great if assertions related to contracts were enabled or disabled by the caller, not only does it not work that way now, I have no idea how it even could work that way.You could have an IDE and build system that makes signatures, unit tests and pre/post conditions essentially read only. Then any modifications to the program specification is either impossible or is flagged as something that is up for negotiation. The build system/compiler can trivially emit contracts to a database. If the contracts change then all code that depend on them will have to be revalidated/recompiled. It is important for D that the D developers keep in mind that the language and the compiler should be designed as separate entities. DMD-internals have too much influence over the language design already.
Feb 05 2015
On Thursday, 5 February 2015 at 08:05:30 UTC, Jonathan M Davis wrote:On Thursday, February 05, 2015 01:33:54 David Nadlinger via Digitalmars-d wrote:DMD is broken. There is no need to break phobos in addition.On Thursday, 5 February 2015 at 01:09:15 UTC, Andrei Alexandrescu wrote:In theory, yes. And then in blocks would provide some value outside of virtual functions. But as it stands, there is _zero_ semantic difference betweenNon-debug mode removes asserts statically. -- AndreiUsing pre-/post-conditions allows the _caller_ to specify whether the checks are run without recompiling the function body, at least in theory.
Feb 05 2015
On Thursday, 5 February 2015 at 01:09:15 UTC, Andrei Alexandrescu wrote:On 2/4/15 4:50 PM, Jonathan Marler wrote:This is correct only if non-debug mode means -release flag specified. For example the dub documentation is misleading saying that -debug flag enables contracts [1]. The contracts are by default enabled, -release disable them. [1] http://code.dlang.org/package-format#build-optionsOn Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:Non-debug mode removes asserts statically. -- AndreiOn 2/4/15 4:40 PM, Jonathan Marler wrote:Only if the function is inlined.On Thursday, 5 February 2015 at 00:35:50 UTC, bearophile wrote:Same about asserts. -- AndreiContracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophileNot to mention that contracts can be removed by the compiler at compile time.
Feb 05 2015
On 2/4/15 4:35 PM, bearophile wrote:Contracts can be read by tools, and they are part of the function signature.The signature part matters only for overridable functions. I agree the part about tooling has merit. -- Andrei
Feb 04 2015
On Thursday, 5 February 2015 at 00:24:15 UTC, Andrei Alexandrescu wrote:I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407: auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low <= high); import std.range : take; return this[low .. $].take(high - low); } What advantage could possibly be in transforming a 5-liner into a 9-liner? Are we really aiming at writing the maximum possible lines of code here and using as many language features as possible everywhere? I think we should dust off that Phobos contributors' guide. Sadly, there is little we can do against the more subtle issues. AndreiVarious things. 1/ the initial is overly long because the styling is wasteful. void foo() in { ... } body { ... } Is simply one line more than not using contracts. 2/ The semantic is not 100% equivalent (well at least the intended semantic) as the in contract should be chosen based on the static type while the implementation on the dynamic one. That mean the contract should tun in the caller. I don't think this is what DMD does currently, but that is what is intended. See for instance : https://issues.dlang.org/show_bug.cgi?id=12247 https://issues.dlang.org/show_bug.cgi?id=6857
Feb 04 2015
On 2/4/15 4:47 PM, deadalnix wrote:1/ the initial is overly long because the styling is wasteful. void foo() in { ... } body { ... } Is simply one line more than not using contracts.Would introduce an exception to our brace-on-its-line rule. I need to take issue with "that code is not using contracts". Using assert _is_ using contracts.2/ The semantic is not 100% equivalent (well at least the intended semantic) as the in contract should be chosen based on the static type while the implementation on the dynamic one. That mean the contract should tun in the caller.Yah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions. Andrei
Feb 04 2015
On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:On 2/4/15 4:47 PM, deadalnix wrote:My definition of an in contract is a condition that the caller is responsible to verify. It appears that your definition is that it's a condition on a function argument (doesn't matter who is responsible). I believe that Walter's definition of Contract programming is the definition I'm referring to. I remember watching one of his talks on contract programming and the performance/optimization benefits he talked about would only apply if a contract made the callee responsible for the asserts. The responsible party, caller/callee matters. As far as I know, D is the first language to allow a function to make the caller responsible for verifying an assert. Even before I saw this in D, I always wondered why no languages provided a way specify this. H.S. Teoh had a good response on why it matters to specify caller/callee so I'll refer to his response instead of re-hashing what he already said.1/ the initial is overly long because the styling is wasteful. void foo() in { ... } body { ... } Is simply one line more than not using contracts.Would introduce an exception to our brace-on-its-line rule. I need to take issue with "that code is not using contracts". Using assert _is_ using contracts.
Feb 04 2015
On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:Yah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions.Putting the contract in the caller is not only useful for overridable functions. 1/ If a lib is compiled in without contract, but your code is compiled with, you get the in contract to run when you call library code, but not the assert within the function. 2/ The optimizer see the properties of the argument when they get to the in contract. This information is lost in the callee, unless inlining goes on. that means the amount of contract the optimizer can remove statically is greater with in contract.
Feb 04 2015
On 2/4/15 5:32 PM, deadalnix wrote:On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:Yah, I understand the potential there. Consider me grudgingly convinced :o). -- AndreiYah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions.Putting the contract in the caller is not only useful for overridable functions. 1/ If a lib is compiled in without contract, but your code is compiled with, you get the in contract to run when you call library code, but not the assert within the function. 2/ The optimizer see the properties of the argument when they get to the in contract. This information is lost in the callee, unless inlining goes on. that means the amount of contract the optimizer can remove statically is greater with in contract.
Feb 04 2015
On Thursday, 5 February 2015 at 01:33:54 UTC, Andrei Alexandrescu wrote:On 2/4/15 5:32 PM, deadalnix wrote:I don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:Yah, I understand the potential there. Consider me grudgingly convinced :o). -- AndreiYah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions.Putting the contract in the caller is not only useful for overridable functions. 1/ If a lib is compiled in without contract, but your code is compiled with, you get the in contract to run when you call library code, but not the assert within the function. 2/ The optimizer see the properties of the argument when they get to the in contract. This information is lost in the callee, unless inlining goes on. that means the amount of contract the optimizer can remove statically is greater with in contract.
Feb 04 2015
On Thu, Feb 05, 2015 at 05:42:57AM +0000, Meta via Digitalmars-d wrote: [...]I don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.I do write contracts in my own code, though not as much as I would've because (1) the syntax is far too verbose, (2) dmd makes a mess of DbC by putting in-contracts in the callee rather than the caller, causing severe limitations in real-life usage, and (3) so far optimizations based on contracts (esp. via assert/assume, that Walter was so insistent on) haven't materialized yet. But then again, I do like to document my code a lot too, so maybe I'm just One Of Those People. *shrug* (I'm not as extreme as bearophile in insisting on putting immutable everywhere, though. Not yet, anyway. :-P) T -- Bare foot: (n.) A device for locating thumb tacks on the floor.
Feb 04 2015
On Thursday, 5 February 2015 at 06:15:39 UTC, H. S. Teoh wrote:On Thu, Feb 05, 2015 at 05:42:57AM +0000, Meta via Digitalmars-d wrote: [...]I've found that the more years of experience I have under my belt, the less documentation I wrote. When I was starting out I was very diligent in doing everything the Correct Way so as to cultivate good habits. I'd find my regression over the years more alarming if I cared enough.I don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.I do write contracts in my own code, though not as much as I would've because (1) the syntax is far too verbose, (2) dmd makes a mess of DbC by putting in-contracts in the callee rather than the caller, causing severe limitations in real-life usage, and (3) so far optimizations based on contracts (esp. via assert/assume, that Walter was so insistent on) haven't materialized yet. But then again, I do like to document my code a lot too, so maybe I'm just One Of Those People. *shrug* (I'm not as extreme as bearophile in insisting on putting immutable everywhere, though. Not yet, anyway. :-P) T
Feb 04 2015
On Thursday, 5 February 2015 at 06:26:17 UTC, Meta wrote:I've found that the more years of experience I have under my belt, the less documentation I wrote. When I was starting out I was very diligent in doing everything the Correct Way so as to cultivate good habits. I'd find my regression over the years more alarming if I cared enough.$0.02: I personally use contracts quite a lot to tighten the screws on my interfaces. I don't like writing documentation, mostly on account of I refactor so aggressively it winds up being wasted effort in a lot of cases (though I do make notes when I think something is complex enough to forget or unlikely to change), so instead I opt to "document" via unittest and assert messages in contracts. One of my main internal packages consists of a set of mixin templates that generate operators from supplied primitives. The release runtime is meant to be light, and mostly offers syntactic sugar (more importantly, unified interfaces with predictable semantics) so code for each layer winds up being between 1:1 and 60:1 contract to body. From a documentation perspective, being able to open up the "out" block and see that the enclosing struct's length values must reflect the values passed to the allocation primitive is nice. Being able to open up the "body" block and see, without the clutter of all the bounds checks and whatnot, opIndex just forwards the call to the access primitive in one line - also nice. I love dbC in D. I think in/out makes things clean and obvious. I could care less about the line count, I use code-folding anyway.
Feb 04 2015
On Thursday, 5 February 2015 at 06:51:35 UTC, Vlad Levenfeld wrote:I could care lessEr, stupid but unfortunately common american english idiom. For non-native speakers, I mean to say I could NOT care less.
Feb 04 2015
On Thursday, 5 February 2015 at 06:55:09 UTC, Vlad Levenfeld wrote:On Thursday, 5 February 2015 at 06:51:35 UTC, Vlad Levenfeld wrote:Thanks. I was firmly convinced that's a typo...I could care lessEr, stupid but unfortunately common american english idiom. For
Feb 05 2015
On Thursday, February 05, 2015 08:13:32 eles via Digitalmars-d wrote:On Thursday, 5 February 2015 at 06:55:09 UTC, Vlad Levenfeld wrote:No. It's just a frustratingly common mistake - like saying "for all intensive purposes" instead of "for all intents and purposes." Unfortunately, many folks couldn't care less about getting it right... - Jonathan M DavisOn Thursday, 5 February 2015 at 06:51:35 UTC, Vlad Levenfeld wrote:Thanks. I was firmly convinced that's a typo...I could care lessEr, stupid but unfortunately common american english idiom. For
Feb 05 2015
On Thursday, 5 February 2015 at 08:22:24 UTC, Jonathan M Davis wrote:No. It's just a frustratingly common mistake - like saying "for all intensive purposes" instead of "for all intents and purposes." Unfortunately, many folks couldn't care less about getting it right...Well, when you grow up hearing it, you reach for the notion and the words just come out before you can apply the filter. Irregardless, same difference.
Feb 05 2015
On 2/5/2015 5:22 PM, Jonathan M Davis via Digitalmars-d wrote:On Thursday, February 05, 2015 08:13:32 eles via Digitalmars-d wrote:I can't phantom that!On Thursday, 5 February 2015 at 06:55:09 UTC, Vlad Levenfeld wrote:No. It's just a frustratingly common mistake - like saying "for all intensive purposes" instead of "for all intents and purposes." Unfortunately, many folks couldn't care less about getting it right... - Jonathan M DavisOn Thursday, 5 February 2015 at 06:51:35 UTC, Vlad Levenfeld wrote:Thanks. I was firmly convinced that's a typo...I could care lessEr, stupid but unfortunately common american english idiom. For
Feb 05 2015
On 2/5/15 5:47 AM, Mike Parker wrote:On 2/5/2015 5:22 PM, Jonathan M Davis via Digitalmars-d wrote:I think we should return to the topic at hand irregardless. -- AndreiOn Thursday, February 05, 2015 08:13:32 eles via Digitalmars-d wrote:I can't phantom that!On Thursday, 5 February 2015 at 06:55:09 UTC, Vlad Levenfeld wrote:No. It's just a frustratingly common mistake - like saying "for all intensive purposes" instead of "for all intents and purposes." Unfortunately, many folks couldn't care less about getting it right... - Jonathan M DavisOn Thursday, 5 February 2015 at 06:51:35 UTC, Vlad Levenfeld wrote:Thanks. I was firmly convinced that's a typo...I could care lessEr, stupid but unfortunately common american english idiom. For
Feb 05 2015
On 2/5/2015 12:22 AM, Jonathan M Davis via Digitalmars-d wrote:No. It's just a frustratingly common mistake - like saying "for all intensive purposes" instead of "for all intents and purposes."What? I thought it was "for all infants and porpoises"!
Feb 05 2015
On Thu, Feb 05, 2015 at 12:03:29PM -0800, Walter Bright via Digitalmars-d wrote:On 2/5/2015 12:22 AM, Jonathan M Davis via Digitalmars-d wrote:What, what? For elephants and porpoises? I thought this was a programming language forum; I must have subscribed to a zoo magazine by mistake! T -- Programming is not just an act of telling a computer what to do: it is also an act of telling other programmers what you wished the computer to do. Both are important, and the latter deserves care. -- Andrew MortonNo. It's just a frustratingly common mistake - like saying "for all intensive purposes" instead of "for all intents and purposes."What? I thought it was "for all infants and porpoises"!
Feb 05 2015
On Thursday, February 05, 2015 12:03:29 Walter Bright via Digitalmars-d wrote:On 2/5/2015 12:22 AM, Jonathan M Davis via Digitalmars-d wrote:LOL. - Jonathan M DavisNo. It's just a frustratingly common mistake - like saying "for all intensive purposes" instead of "for all intents and purposes."What? I thought it was "for all infants and porpoises"!
Feb 05 2015
On Thursday, 5 February 2015 at 06:15:39 UTC, H. S. Teoh wrote:On Thu, Feb 05, 2015 at 05:42:57AM +0000, Meta via Digitalmars-d wrote: [...]I miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.I don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.I do write contracts in my own code, though not as much as I would've because (1) the syntax is far too verbose, (2) dmd makes a mess of DbC by putting in-contracts in the callee rather than the caller, causing severe limitations in real-life usage, and (3) so far optimizations based on contracts (esp. via assert/assume, that Walter was so insistent on) haven't materialized yet. But then again, I do like to document my code a lot too, so maybe I'm just One Of Those People. *shrug* (I'm not as extreme as bearophile in insisting on putting immutable everywhere, though. Not yet, anyway. :-P) T
Feb 04 2015
On Thursday, 5 February 2015 at 07:28:36 UTC, Paulo Pinto wrote:I miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.Conceptually the precondition is a specification that the caller has to guarantee, and the postcondition is a specification that the callee guarantees. The enforcement of the contract specification should be done by the build system which is "neutral". I.e. the contractors who wrote the code for the callers and callees may try to subvert the contract, but the build system should ideally prevent this. This is of course messed up in D, since you don't have a separate specification independent of the implementation, but you could still verify the D code against a specification to prevent contractors from subverting contracts. The thought of having the signature/specification before the implementation was a good one, but readability suffers from having all the braces. So the D syntax is not as usable as it should be. I think D should do this in the body like other languages: func(){ require(...); ensure(…); ... function body ... } or func(){ pre(...); post(…); ... function body ... } or func(){ pre_assert(...); post_assert(…); ... function body ... }
Feb 04 2015
On Thursday, 5 February 2015 at 07:28:36 UTC, Paulo Pinto wrote:I miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.There was a huge discussion here: https://issues.dlang.org/show_bug.cgi?id=6857 Long story short: it was done in Eiffel that way for implementation reason, other language are cargo culting eiffel, and putting in contract in the caller is the right thing to do.
Feb 05 2015
On Thursday, 5 February 2015 at 09:02:05 UTC, deadalnix wrote:On Thursday, 5 February 2015 at 07:28:36 UTC, Paulo Pinto wrote:So the caller can break the contract without any consideration for what values the input arguments are valid?! There is a reason why the industry at large has adopted the Eiffel way. - PauloI miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.There was a huge discussion here: https://issues.dlang.org/show_bug.cgi?id=6857 Long story short: it was done in Eiffel that way for implementation reason, other language are cargo culting eiffel, and putting in contract in the caller is the right thing to do.
Feb 05 2015
On Thursday, 5 February 2015 at 09:33:12 UTC, Paulo Pinto wrote:So the caller can break the contract without any consideration for what values the input arguments are valid?! There is a reason why the industry at large has adopted the Eiffel way.Yes, it is called cargo cult.
Feb 05 2015
On Thursday, 5 February 2015 at 10:09:34 UTC, deadalnix wrote:On Thursday, 5 February 2015 at 09:33:12 UTC, Paulo Pinto wrote:I am out.So the caller can break the contract without any consideration for what values the input arguments are valid?! There is a reason why the industry at large has adopted the Eiffel way.Yes, it is called cargo cult.
Feb 05 2015
On Thursday, 5 February 2015 at 11:05:42 UTC, Paulo Pinto wrote:On Thursday, 5 February 2015 at 10:09:34 UTC, deadalnix wrote:Out of the rabbit hole, like Alice in Wonderland? But you are right, of course. The caller should not be able to subvert the contract. Only the build system should control contract enforcement (e.g. the integration team, system architect etc, not implementors) The D design process is very much a cargo cult thing...On Thursday, 5 February 2015 at 09:33:12 UTC, Paulo Pinto wrote:I am out.So the caller can break the contract without any consideration for what values the input arguments are valid?! There is a reason why the industry at large has adopted the Eiffel way.Yes, it is called cargo cult.
Feb 05 2015
On Thursday, 5 February 2015 at 11:43:28 UTC, Ola Fosheim Grøstad wrote:On Thursday, 5 February 2015 at 11:05:42 UTC, Paulo Pinto wrote:I believe the Eiffel way, just like the industry does, with endless tools and processes that follow and validate DbC. Since I don't have any use for D at work, besides being a language geek, I don't see the point to argue for whatever might be the outcome, other than producing noise and being part of the problem. So, I am out of this thread. -- PauloOn Thursday, 5 February 2015 at 10:09:34 UTC, deadalnix wrote:Out of the rabbit hole, like Alice in Wonderland? But you are right, of course. The caller should not be able to subvert the contract. Only the build system should control contract enforcement (e.g. the integration team, system architect etc, not implementors) The D design process is very much a cargo cult thing...On Thursday, 5 February 2015 at 09:33:12 UTC, Paulo Pinto wrote:I am out.So the caller can break the contract without any consideration for what values the input arguments are valid?! There is a reason why the industry at large has adopted the Eiffel way.Yes, it is called cargo cult.
Feb 05 2015
On Thursday, 5 February 2015 at 12:39:18 UTC, Paulo Pinto wrote:I believe the Eiffel way, just like the industry does, with endless tools and processes that follow and validate DbC.I believe Ada allows the separation of interface and implementation, and providing the contract in the interface. So it is less dependent on tools. Ada with SPARK 2014 makes D look like it is stuck in the 80s: 4.2. Subprogram Contracts 4.2.1. Preconditions 4.2.2. Postconditions 4.2.3. Contract Cases 4.2.4. Data Dependencies 4.2.5. Flow Dependencies 4.2.6. State Abstraction and Contracts 4.2.6.1. State Abstraction and Dependencies 4.2.6.2. State Abstraction and Functional Contracts 4.3. Package Contracts 4.3.1. State Abstraction 4.3.2. Package Initialization 4.3.3. Package Initial Condition 4.3.4. Interfaces to the Physical World 4.3.4.1. Volatile Variables 4.3.4.2. Flavors of Volatile Variables 4.3.4.3. External State Abstraction 4.4. Type Contracts 4.4.1. Scalar Ranges 4.4.2. Static Predicates 4.4.3. Record Discriminants 4.4.4. Default Initial Condition 4.5. Specification Features 4.5.1. Attribute Old 4.5.1.1. In a Postcondition 4.5.1.2. In Contract Cases 4.5.1.3. In a Potentially Unevaluated Expression 4.5.2. Attribute Result 4.5.3. Attribute Loop_Entry 4.5.4. Attribute Update 4.5.5. Conditional Expressions 4.5.6. Quantified Expressions 4.5.7. Expression Functions 4.5.8. Ghost Code 4.5.8.1. Ghost Functions 4.5.8.2. Ghost Variables Case 1: Keeping Intermediate Values Case 2: Keeping Memory of Previous State Case 3: Logging Previous Events 4.5.8.3. Ghost Types 4.5.8.4. Ghost Procedures 4.5.8.5. Ghost Packages 4.5.8.6. Imported Ghost Subprograms 4.6. Assertion Pragmas 4.6.1. Pragma Assert 4.6.2. Loop Invariants 4.6.3. Loop Variants 4.6.4. Pragma Assume 4.6.5. Pragma Assert_And_Cut Yep, D has some serious competition in systems programming and this is just extensions to an old pragmatic language... there are probably more advanced stuff waiting to coming out of research languages...
Feb 05 2015
Ola Fosheim Grøstad:Ada with SPARK 2014 makes D look like it is stuck in the 80s: 4.2. Subprogram Contracts 4.2.1. Preconditions 4.2.2. Postconditions 4.2.3. Contract Cases 4.2.4. Data Dependencies 4.2.5. Flow Dependencies 4.2.6. State Abstraction and Contracts 4.2.6.1. State Abstraction and Dependencies 4.2.6.2. State Abstraction and Functional Contracts 4.3. Package Contracts 4.3.1. State Abstraction 4.3.2. Package Initialization 4.3.3. Package Initial Condition 4.3.4. Interfaces to the Physical World 4.3.4.1. Volatile Variables 4.3.4.2. Flavors of Volatile Variables 4.3.4.3. External State Abstraction 4.4. Type Contracts 4.4.1. Scalar Ranges 4.4.2. Static Predicates 4.4.3. Record Discriminants 4.4.4. Default Initial Condition 4.5. Specification Features 4.5.1. Attribute Old 4.5.1.1. In a Postcondition 4.5.1.2. In Contract Cases 4.5.1.3. In a Potentially Unevaluated Expression 4.5.2. Attribute Result 4.5.3. Attribute Loop_Entry 4.5.4. Attribute Update 4.5.5. Conditional Expressions 4.5.6. Quantified Expressions 4.5.7. Expression Functions 4.5.8. Ghost Code 4.5.8.1. Ghost Functions 4.5.8.2. Ghost Variables Case 1: Keeping Intermediate Values Case 2: Keeping Memory of Previous State Case 3: Logging Previous Events 4.5.8.3. Ghost Types 4.5.8.4. Ghost Procedures 4.5.8.5. Ghost Packages 4.5.8.6. Imported Ghost Subprograms 4.6. Assertion Pragmas 4.6.1. Pragma Assert 4.6.2. Loop Invariants 4.6.3. Loop Variants 4.6.4. Pragma Assume 4.6.5. Pragma Assert_And_CutThat seems a bit too much for the average human to handle :-) Sometimes features help, but that list seems excessive for a language that is not meant for high integrity systems as D. Bye, bearophile
Feb 06 2015
On Friday, 6 February 2015 at 10:08:29 UTC, bearophile wrote:That seems a bit too much for the average human to handle :-) Sometimes features help, but that list seems excessive for a language that is not meant for high integrity systems as D.So D has to decide what development scenario it wants to compete in. There are advanced competitive alternatives for specific system development scenarios with C-like performance. A wide partial feature set only impress programmers who don't know the field, but underwhelm those who actually look for a particular feature set. Having 70% coverage of what the competitors provide for a development scenario is not good enough. D feature set currently does not cut it in: - interactive/realtime - low memory usage/manual memory management - numeric analysis/SIMD - verification - high concurrency/low latency - dataflow/reactive - hardware programming/no runtime/intrinsics - system integration (xml etc) - rapid prototyping - native gui applications So where is D going to make a dent? If you want safer C-like programming you are up against: - various C platforms/tooling - C++14, advanced tooling (analysis, instrumentation), MPX - Ada/SPARK 2014 - Rust If safe/ trusted/ system is not the main selling point for D then it has to provide one of the others. E.g. easy SIMD, unique_ptr style memory management etc.
Feb 06 2015
On Thursday, 5 February 2015 at 11:05:42 UTC, Paulo Pinto wrote:On Thursday, 5 February 2015 at 10:09:34 UTC, deadalnix wrote:To be frankly brutal, you were never in. You presented no argument.On Thursday, 5 February 2015 at 09:33:12 UTC, Paulo Pinto wrote:I am out.So the caller can break the contract without any consideration for what values the input arguments are valid?! There is a reason why the industry at large has adopted the Eiffel way.Yes, it is called cargo cult.
Feb 05 2015
On Thursday, 5 February 2015 at 17:32:23 UTC, deadalnix wrote:On Thursday, 5 February 2015 at 11:05:42 UTC, Paulo Pinto wrote:I did, by stating that the way Eiffel does is how it is supposed to be. Also mentioned that by giving the callers control over pre-conditions is breaking the notion of what Design by Contract stands for. If the caller can disable pre-conditions of the callee, then the premisses of Design by Contract just go out of the window. I was dry with my statement, because by calling the verification industry as cargo cultists, I could only depreend no argument on my side would change your opinion. As far as I can tell, D in production doesn't even reach 1% of production systems out there coded in Eiffel, Ada 2012, .NET Code Lockheed Martin and so on, wherever it is used. Yet, here goes the discussion against what production quality systems have been delivering because they are all wrong and its developers are plain cargo cultists. Anyway, as a simple D dabbler I should learn to keep quiet, as I am just adding noise to the NG. -- PauloOn Thursday, 5 February 2015 at 10:09:34 UTC, deadalnix wrote:To be frankly brutal, you were never in. You presented no argument.On Thursday, 5 February 2015 at 09:33:12 UTC, Paulo Pinto wrote:I am out.So the caller can break the contract without any consideration for what values the input arguments are valid?! There is a reason why the industry at large has adopted the Eiffel way.Yes, it is called cargo cult.
Feb 05 2015
On 2/5/15 11:19 AM, Paulo Pinto wrote:I did, by stating that the way Eiffel does is how it is supposed to be.That issue reveals that Eiffel essentially contradicts directly its creators' book. -- Andrei
Feb 05 2015
On Thursday, 5 February 2015 at 19:19:43 UTC, Paulo Pinto wrote:In the links that were provided to you, you'll see one instance of Eiffel's designer saying that this was done like this at first for ease of implementation and then it stated like this for historical reason, and that the sensible thing to do is to put the check in the caller. No, if you want to say that Eiffel is the way it should, while even its creator think this is not the case, you have to substantiate. Saying that Eiffel do it in some way is certainly a fact, but not an argument.To be frankly brutal, you were never in. You presented no argument.I did, by stating that the way Eiffel does is how it is supposed to be.I was dry with my statement, because by calling the verification industry as cargo cultists, I could only depreend no argument on my side would change your opinion.In fact this is very possible to change my opinion. If you read the bug report, you'll notice that I'm defending a position similar to yours at first. Considering that someone who contradict you cannot be convinced anyway is a lazy. I'm not changing my position because no new argument have been presented.
Feb 05 2015
On Thursday, 5 February 2015 at 09:02:05 UTC, deadalnix wrote:On Thursday, 5 February 2015 at 07:28:36 UTC, Paulo Pinto wrote:Wow. Amazing discussion.I miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.There was a huge discussion here: https://issues.dlang.org/show_bug.cgi?id=6857
Feb 05 2015
On Thursday, 5 February 2015 at 10:51:32 UTC, eles wrote:On Thursday, 5 February 2015 at 09:02:05 UTC, deadalnix wrote:But it ends with: "Andrei Alexandrescu 2013-01-10 09:14:02 UTC Walter: would you preapprove this?" Well, we are now 2 years (and some) later.On Thursday, 5 February 2015 at 07:28:36 UTC, Paulo Pinto wrote:Wow. Amazing discussion.I miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.There was a huge discussion here: https://issues.dlang.org/show_bug.cgi?id=6857
Feb 05 2015
"eles" wrote in message news:sybluuitxifnwrwzgbpo forum.dlang.org...But it ends with: "Andrei Alexandrescu 2013-01-10 09:14:02 UTC Walter: would you preapprove this?" Well, we are now 2 years (and some) later.I don't speak for Walter, but I expect if it can be implemented in a sane way it will make it into the compiler and spec.
Feb 05 2015
On 2/5/15 2:55 AM, eles wrote:On Thursday, 5 February 2015 at 10:51:32 UTC, eles wrote:It has been preapproved. The challenge now is implementing it. -- AndreiOn Thursday, 5 February 2015 at 09:02:05 UTC, deadalnix wrote:But it ends with: "Andrei Alexandrescu 2013-01-10 09:14:02 UTC Walter: would you preapprove this?" Well, we are now 2 years (and some) later.On Thursday, 5 February 2015 at 07:28:36 UTC, Paulo Pinto wrote:Wow. Amazing discussion.I miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.There was a huge discussion here: https://issues.dlang.org/show_bug.cgi?id=6857
Feb 05 2015
On 2/5/15 9:31 AM, Andrei Alexandrescu wrote:On 2/5/15 2:55 AM, eles wrote:Better put: it had been preapproved back in Jan 2013 and is still looking for someone to fix it. -- AndreiOn Thursday, 5 February 2015 at 10:51:32 UTC, eles wrote:It has been preapproved. The challenge now is implementing it. -- AndreiOn Thursday, 5 February 2015 at 09:02:05 UTC, deadalnix wrote:But it ends with: "Andrei Alexandrescu 2013-01-10 09:14:02 UTC Walter: would you preapprove this?" Well, we are now 2 years (and some) later.On Thursday, 5 February 2015 at 07:28:36 UTC, Paulo Pinto wrote:Wow. Amazing discussion.I miss the point about in. DbC as presentend by Eiffel and adopted in .NET, Ada among others, the complete contract is on the callee. It doesn't make sense otherwise.There was a huge discussion here: https://issues.dlang.org/show_bug.cgi?id=6857
Feb 05 2015
"Meta" wrote in message news:ejqtxksoifmqzetllaqw forum.dlang.org...I don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.Would you be more likely to write contracts if something like this was implemented? https://github.com/D-Programming-Language/dmd/pull/3799 I want to check contracts at compile time, when possible. For me this would make contracts 1000x more useful.
Feb 04 2015
On Thursday, 5 February 2015 at 06:41:59 UTC, Daniel Murphy wrote:"Meta" wrote in message news:ejqtxksoifmqzetllaqw forum.dlang.org...I have seen that PR previously, and I do hope it gets merged. It is a step in the right direction; contracts may turn out to be a veritable goldmine of opportunities from optimization, such as Walter's desire to have assert() also mean assume(). Using contracts for optimization purposes is really a win-win, as it would make contract-based code both more correct AND faster. I think the best way to evangelize DbC is not that it's the correct thing to do, but because it makes code faster. That's obviously not the case with D yet, but I hope we get there someday.I don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.Would you be more likely to write contracts if something like this was implemented? https://github.com/D-Programming-Language/dmd/pull/3799 I want to check contracts at compile time, when possible. For me this would make contracts 1000x more useful.
Feb 05 2015
"Meta" wrote in message news:etibhdbtswksyksznfxv forum.dlang.org...I have seen that PR previously, and I do hope it gets merged. It is a step in the right direction; contracts may turn out to be a veritable goldmine of opportunities from optimization, such as Walter's desire to have assert() also mean assume(). Using contracts for optimization purposes is really a win-win, as it would make contract-based code both more correct AND faster. I think the best way to evangelize DbC is not that it's the correct thing to do, but because it makes code faster. That's obviously not the case with D yet, but I hope we get there someday.Yes, optimization is another nice possibility. I think there is a lot of untapped potential in using contracts to pass extra information to the compiler.
Feb 05 2015
On 2/5/15 1:53 AM, Daniel Murphy wrote:Yes, optimization is another nice possibility. I think there is a lot of untapped potential in using contracts to pass extra information to the compiler.I agree. One actionable - albeit crazy :o) - idea is to make __FILE__, __LINE__, __MODULE__ etc. inside contracts bind to the caller context. Then all failures blame straight to the caller code. -- Andrei
Feb 05 2015
"Andrei Alexandrescu" wrote in message news:mb03nt$1lhr$1 digitalmars.com...I agree. One actionable - albeit crazy :o) - idea is to make __FILE__, __LINE__, __MODULE__ etc. inside contracts bind to the caller context. Then all failures blame straight to the caller code. -- AndreiUnfortunately that's not practical until contracts have been changed to run from the caller's side, as there is no way to pass them through the called caller's location correctly.
Feb 05 2015
On Thursday, February 05, 2015 17:42:11 Daniel Murphy via Digitalmars-d wrote:"Meta" wrote in message news:ejqtxksoifmqzetllaqw forum.dlang.org...If the semantics of auto foo(T arg) in { assert(something about arg); } body { ... } and auto foo(T arg) { assert(something about arg); ... } actually are different, and the in block provides a useful difference, then there's value in having in blocks. Without that, IMHO, they're just visual noise, even if you use a different coding style that condenses them more, e.g. auto foo(T arg) in { assert(something about arg); } body { ... } So, if we can change the semantics of in and out blocks so that they provide actual value, then there's definitely value in using them. But until then, as far as I'm concerned, they're just cruft that should be avoided. Having some sort of compile time checking of contracts would potentally be a case where in blocks would be of value, though I really don't see much difference between checking the assertions in an in block and checking any other assertions at compile time that can be checked at compile time - especially if they're at the beginning of a function. The real killer feature would be if we could figure out how to make it so that contracts are controlled by the call site instead of being compiled out when the function itself is compiled without assertions enabled. But I have no idea how we could do that given that we can have function prototypes without the actual source code being visible at the call site. - Jonathan M DavisI don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.Would you be more likely to write contracts if something like this was implemented? https://github.com/D-Programming-Language/dmd/pull/3799 I want to check contracts at compile time, when possible. For me this would make contracts 1000x more useful.
Feb 05 2015
On Thursday, 5 February 2015 at 08:25:56 UTC, Jonathan M Davis wrote:case where in blocks would be of value, though I really don't see much difference between checking the assertions in an in block and checking any other assertions at compile time that can be checked at compile time -The difference is that implementation asserts() are part of debugging within a module, while contracts may be active in release mode so that you know which module failed and which subcontractor to call to fix it.
Feb 05 2015
On Thursday, February 05, 2015 08:31:08 via Digitalmars-d wrote:On Thursday, 5 February 2015 at 08:25:56 UTC, Jonathan M Davis wrote:There is no such difference in the current implementation. assertions inside of in and out blocks are no different from assertions inside of the functions themselves with regards to when they are compiled in or not. The _only_ difference between having an assertion inside of an in block and having it at the beginning of the function is that if the function is a virtual function, then the rules of inheritance of DbC are taken into account, which IIRC means that only one of the functions in the inheritance chain has to have its in block pass, and the others are allowed to fail, whereas if it were an out block, all of them would have to pass. Regardless, if you have auto foo(T t) in { assert(something about t); } body { ... } it's _identical_ to auto foo(T t) { assert(something about t); ... } with regards to semantics. Ideally, what's in the in block would be compiled in if the caller is compiled with assertions enabled with no regard to whether the library with foo in it was compiled with assertions enabled or not, but that's not how it works. And because D allows for function prototypes where the implementation is hidden, it's not at all obvious how it would even be possible for anything in an in our out block could be compiled in or not based on the caller rather than the function itself. - Jonathan M Daviscase where in blocks would be of value, though I really don't see much difference between checking the assertions in an in block and checking any other assertions at compile time that can be checked at compile time -The difference is that implementation asserts() are part of debugging within a module, while contracts may be active in release mode so that you know which module failed and which subcontractor to call to fix it.
Feb 05 2015
On Thursday, 5 February 2015 at 09:43:53 UTC, Jonathan M Davis wrote:There is no such difference in the current implementation. assertions inside of in and out blocks are no different from assertions inside of the functions themselves with regards to when they are compiled in or not.But that is a compiler issue, and not a general issue with interface contracts for components. What is desirable is to have "asserts with semantics attached to them" done in a way that works with how you do formal program verification. I also would like to see loop invariants getting a special treatment.pass. Regardless, if you have auto foo(T t) in { assert(something about t); } body { ... } it's _identical_ to auto foo(T t) { assert(something about t); ... }Yes and just having an alias "precondition" for "assert" would go a long way in that case. And if the compiler recognize it, it could also do the magic for inheritance.with regards to semantics. Ideally, what's in the in block would be compiled in if the caller is compiled with assertions enabled with no regard to whether the library with foo in it was compiled with assertions enabled or not, but that's not how it works. And because D allows for function prototypes where the implementation is hidden, it's not at all obvious how it would even be possible for anything in an in our out block could be compiled in or not based on the caller rather than the function itself.I actually think that interface contracts (and ideally unit tests) should be part of a specification language that is shared across implementation languages. Then the implementation language has to provide mechanisms to make it possible to test that the transitions between components abide interface contracts. The ideal build system would allow you to have one specification with pre/post conditions between modules and then let the build system link together "LLVM IRish object code" with checks between modules injected duing whole program optimized "linking". That way you could build large systems that are more robust using code from C, C++, Ada, Fortran, Rust, D... governed by one unified specification. And a combination of proof verification and an optimizing linker could elide pre/post-condition tests that are redundant, either before a formal proof exists that only needs to be verified or because the condition is trivially satisifie, e.g.: ---- func(int i){ precondition(i>0); ... } ---- func(3); -----
Feb 05 2015
On Thursday, 5 February 2015 at 09:43:53 UTC, Jonathan M Davis wrote:There is no such difference in the current implementation. assertions inside of in and out blocks are no different from assertions inside of the functions themselves with regards to when they are compiled in or not.Good point. One problem is that base asserts throw exceptions on loosening contract on overriding method. Asserts in contracts can behave differently, e.g. derived contract can call base contract with a parameter asking to not throw on failure.
Feb 05 2015
On Thursday, February 05, 2015 12:34:34 Kagamin via Digitalmars-d wrote:On Thursday, 5 February 2015 at 09:43:53 UTC, Jonathan M Davis wrote:Virtual functions is the _one_ place where using in and out blocks actually makes a difference, and at the moment, it's the only reason that it makes sense for them to exist in the language IMHO - though that definitely changes if we're able to make it so that whether the contracts are run is determined by the caller rather than whoever compiled the function itself. - Jonathan M DavisThere is no such difference in the current implementation. assertions inside of in and out blocks are no different from assertions inside of the functions themselves with regards to when they are compiled in or not.Good point. One problem is that base asserts throw exceptions on loosening contract on overriding method. Asserts in contracts can behave differently, e.g. derived contract can call base contract with a parameter asking to not throw on failure.
Feb 05 2015
"Jonathan M Davis via Digitalmars-d" wrote in message news:mailman.6014.1423124756.9932.digitalmars-d puremagic.com...So, if we can change the semantics of in and out blocks so that they provide actual value, then there's definitely value in using them. But until then, as far as I'm concerned, they're just cruft that should be avoided.Yes, and we are almost certainly going to change it so that the caller's flags determine if contracts are executed, not the callee's. That alone is enough to make explicit contract blocks worthwhile.Having some sort of compile time checking of contracts would potentally be a case where in blocks would be of value, though I really don't see much difference between checking the assertions in an in block and checking any other assertions at compile time that can be checked at compile time - especially if they're at the beginning of a function.IMO they have a different meaning either way. void func(int x) in { assert(x > 6); // If this assert fails the caller was incorrect } body { assert(x > 7); // If this assert fails then 'func' has a bug. } While these look similar, they vary in where they assign blame. It would not be valid for the compiler to give an error at the caller if the second assert is known to fail, because it's not the caller's fault. It's not uncommon to stub out unimplemented functions with assert(0), and this is not an error for the caller either. Without 'in' blocks we lose this distinction.The real killer feature would be if we could figure out how to make it so that contracts are controlled by the call site instead of being compiled out when the function itself is compiled without assertions enabled. But I have no idea how we could do that given that we can have function prototypes without the actual source code being visible at the call site.It's possible, it's just not easy. Contracts would not be called if the prototype didn't have them, so di files would likely have the contracts retained.
Feb 05 2015
On Thursday, February 05, 2015 21:01:19 Daniel Murphy via Digitalmars-d wrote:"Jonathan M Davis via Digitalmars-d" wrote in message news:mailman.6014.1423124756.9932.digitalmars-d puremagic.com...Well, if we can change it so that whether the contracts are run or not is determined by the caller and not the callee, then using them would definitely be worth it. But as long as that's not the case, it's not at all worth the visual noise IMHO to use in and out blocks IMHO. And if/once we change it so that whether the in and out blocks are run is determined by the caller, the visual noise will still be annoying enough to make it so that I won't be in a hurry to add them unless they're adding real value rather than just some additional, nice-to-have checks. - Jonathan M DavisThe real killer feature would be if we could figure out how to make it so that contracts are controlled by the call site instead of being compiled out when the function itself is compiled without assertions enabled. But I have no idea how we could do that given that we can have function prototypes without the actual source code being visible at the call site.It's possible, it's just not easy. Contracts would not be called if the prototype didn't have them, so di files would likely have the contracts retained.
Feb 05 2015
"Jonathan M Davis via Digitalmars-d" wrote in message news:mailman.6026.1423131941.9932.digitalmars-d puremagic.com...Well, if we can change it so that whether the contracts are run or not is determined by the caller and not the callee, then using them would definitely be worth it. But as long as that's not the case, it's not at all worth the visual noise IMHO to use in and out blocks IMHO. And if/once we change it so that whether the in and out blocks are run is determined by the caller, the visual noise will still be annoying enough to make it so that I won't be in a hurry to add them unless they're adding real value rather than just some additional, nice-to-have checks.I agree, and that's a big part of why I opened that pull request. The idea of contracts is nice but we need some real tangible benefits from them to encourage their use.
Feb 05 2015
On Thursday, 5 February 2015 at 05:42:59 UTC, Meta wrote:On Thursday, 5 February 2015 at 01:33:54 UTC, Andrei Alexandrescu wrote:I also make all my variables immutable unless I can't. Which is annoyingly and surprisingly often. Sometimes I have to downgrade to const (usually because of strings), sometimes I have to rather sadly go back to auto. I never like it when I do. I should probably do more contract programming. immutable is good. immutable is your friend. AFAIC, mutable state is the root of all evil. AtilaOn 2/4/15 5:32 PM, deadalnix wrote:I don't know about others (besides Beatophile, who religiously adheres to writing contacts), but putting contracts on functions is a hassle. I never do it unless I'm feeling particularly full of divine fervor. It's a lot like making all variables that don't need to be changed immutable (another thing which only Bearophile seems to do) or properly documenting code. Strong optimization guarantees from contracts would go a long way in convincing people to actually write them (although I guess that's not what you want; Perhaps you changed your mind). It's a chicken and egg problem.On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:Yah, I understand the potential there. Consider me grudgingly convinced :o). -- AndreiYah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions.Putting the contract in the caller is not only useful for overridable functions. 1/ If a lib is compiled in without contract, but your code is compiled with, you get the in contract to run when you call library code, but not the assert within the function. 2/ The optimizer see the properties of the argument when they get to the in contract. This information is lost in the callee, unless inlining goes on. that means the amount of contract the optimizer can remove statically is greater with in contract.
Feb 05 2015
On 2/4/2015 5:32 PM, deadalnix wrote:On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:I was prepared to argue with you, but you're right on all points. Nicely done. Thanks!Yah, I agree "in" is useful for overridable functions. In fact I'd say it's useful _only_ for overridable functions.Putting the contract in the caller is not only useful for overridable functions. 1/ If a lib is compiled in without contract, but your code is compiled with, you get the in contract to run when you call library code, but not the assert within the function. 2/ The optimizer see the properties of the argument when they get to the in contract. This information is lost in the callee, unless inlining goes on. that means the amount of contract the optimizer can remove statically is greater with in contract.
Feb 05 2015
On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:Would introduce an exception to our brace-on-its-line rule.Will I start the next world war if I mention this rule is only useful to eat vertical space on my screen (especially when using contracts) ?
Feb 04 2015
On Thu, Feb 05, 2015 at 01:34:47AM +0000, deadalnix via Digitalmars-d wrote:On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:Which is already blatantly violated everywhere in single-line functions.Would introduce an exception to our brace-on-its-line rule.Will I start the next world war if I mention this rule is only useful to eat vertical space on my screen (especially when using contracts) ?It's an example of blindly adhering to the letter of the rule while violating the spirit of the rule, which is to make code more readable. T -- Change is inevitable, except from a vending machine.
Feb 04 2015
On Thursday, 5 February 2015 at 01:53:17 UTC, H. S. Teoh wrote:It's an example of blindly adhering to the letter of the rule while violating the spirit of the rule, which is to make code more readable. TAhhh...thanks for this. I've been searching for an eloquent way to say this for a while :)
Feb 04 2015
On 2/4/15 6:10 PM, Jonathan Marler wrote:On Thursday, 5 February 2015 at 01:53:17 UTC, H. S. Teoh wrote:Hey, I've been saying that all over https://issues.dlang.org/show_bug.cgi?id=14125 :o). -- AndreiIt's an example of blindly adhering to the letter of the rule while violating the spirit of the rule, which is to make code more readable. TAhhh...thanks for this. I've been searching for an eloquent way to say this for a while :)
Feb 04 2015
On 05/02/2015 01:50, H. S. Teoh via Digitalmars-d wrote:On Thu, Feb 05, 2015 at 01:34:47AM +0000, deadalnix via Digitalmars-d wrote:We really should support => syntax for these instead, they are very common. Consistent with lambdas.Which is already blatantly violated everywhere in single-line functions.On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:Would introduce an exception to our brace-on-its-line rule.
Feb 05 2015
On 2/4/15 5:34 PM, deadalnix wrote:On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:As a Facebook fellow, I wouldn't mind Egyptian braces. But they won't happen. -- AndreiWould introduce an exception to our brace-on-its-line rule.Will I start the next world war if I mention this rule is only useful to eat vertical space on my screen (especially when using contracts) ?
Feb 04 2015
On Thursday, 5 February 2015 at 01:34:49 UTC, deadalnix wrote:On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:If contracts would support single statements: auto opSlice(size_t low, size_t high) in assert(low <= high); in assert(0 == 0); out(r) assert(r.length == high - low); out(r) assert(!r.empty); { import std.range : take; return this[low .. $].take(high - low); }Would introduce an exception to our brace-on-its-line rule.Will I start the next world war if I mention this rule is only useful to eat vertical space on my screen (especially when using contracts) ?
Feb 05 2015
On 05/02/2015 08:56, Kagamin wrote:On Thursday, 5 February 2015 at 01:34:49 UTC, deadalnix wrote:+1, but with the statements in the function body please: auto opSlice(size_t low, size_t high) { in assert(low <= high); in assert(0 == 0); out(r) assert(r.length == high - low); out(r) assert(!r.empty); import std.range : take; return this[low .. $].take(high - low); } I think that reads better. For ease of implementation inline contracts could be required to come before any runtime variables/code.On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:If contracts would support single statements:Would introduce an exception to our brace-on-its-line rule.Will I start the next world war if I mention this rule is only useful to eat vertical space on my screen (especially when using contracts) ?
Feb 05 2015
On Wed, Feb 04, 2015 at 04:24:14PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407: auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low <= high); import std.range : take; return this[low .. $].take(high - low); }I disagree. Putting the assert in the contract means you're putting the onus on the *caller* to ensure parameters are sane. An assert inside the function body should not be vetting function arguments; that's the wrong use of assert. Asserts inside the function body should be checking for sanity *within* the function body. Requirements on parameter values are something that the *caller* should ensure, and therefore should be in the in-contract, so that the documentation will include it, and readers of the code will know what are the correct arguments to pass (they should not need to read the function body to know this). The fact that currently in-contracts generate the asserts in the callee rather than the caller (which is probably what led you to your conclusions) is a long-standing mis-implementation of DbC that, one could hope, will finally get fixed now that it is receiving some spotlight. In-contracts should be generated in the *caller*, so that any breach of contract will fail on the caller's side. This is a particularly major problem in shared libraries: when you ship a library, you generally compile it with -release, but since in-contracts are emitted in the callee's body, the asserts are skipped in -release mode, so the result is that there is *no* DbC in the shipped library. This alone puts a big dent in the usefulness of DbC in D, reducing it to nothing more than pretty (or, in this case, not-so-pretty!) syntax for what's otherwise nothing more than a glorified assert. T -- "I suspect the best way to deal with procrastination is to put off the procrastination itself until later. I've been meaning to try this, but haven't gotten around to it yet. " -- swr
Feb 04 2015
On Wednesday, February 04, 2015 16:24:14 Andrei Alexandrescu via Digitalmars-d wrote:I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407: auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low <= high); import std.range : take; return this[low .. $].take(high - low); } What advantage could possibly be in transforming a 5-liner into a 9-liner? Are we really aiming at writing the maximum possible lines of code here and using as many language features as possible everywhere? I think we should dust off that Phobos contributors' guide. Sadly, there is little we can do against the more subtle issues.As far as I can tell, there is zero reason to use in blocks aside from with classes, since with virtual functions, inheritance comes into play, and the semantics aren't the same. But for the vast majority of functions, I totally agree that using an in block is just visual noise. Similarly, I think that out blocks are pretty useless. They're of some value when you have multiple return statements and want to check something when the function exits, but in the vast majority of cases, what you're testing with an out contract is what unit tests would be testing, in which case, the out blocks don't really add anything, and since they're forced to be general, you can't test for specific results like you can with a unit test. Sometimes, testing something in the out block can be useful, but in my experience, unit tests almost always take care of it. So, in most cases, out contract blocks don't really add anything IMHO and are pretty pointless (though the exception of virtual functions applies in this case as well). So, while I totally agree that contract programming is valuable, I don't think that the special syntax that D provides for it is of much value except in the case of virtual functions. And the fact that that syntax is so noisy (especially when there's only one assertion) makes it kind of ridiculous IMHO to use in blocks or out blocks on non-virtual functions. - Jonathan M Davis
Feb 05 2015
On Thursday, 5 February 2015 at 08:01:06 UTC, Jonathan M Davis wrote:the function exits, but in the vast majority of cases, what you're testing with an out contract is what unit tests would be testing, in which case, the out blocks don't really add anything, and since they're forced to be general, you can't test for specific results like you can with a unit test.That would be true if: - the unit test was doing exhaustive testing - the unit test is fully specified - the unit test is proven correct But post conditions that are part of a specification can in theory be used for optimization when you link object files from different sources. So you can change the implementation of one object file with only linking as long as the specification itself does not change. Well, if you had a separate specification...
Feb 05 2015
On Thursday, February 05, 2015 08:13:31 via Digitalmars-d wrote:On Thursday, 5 February 2015 at 08:01:06 UTC, Jonathan M Davis wrote:If you're not doing exhaustive unit testing, you're almost certainly doing it wrong. And what you _can_ test when a function is exiting without knowing exactly what the input was and what the corresponding output is supposed to be is so minimal to be borderline useless. For something like sort, you can check that the range is sorted on exit (though that's so expensive to check that it's kind of ridiculous to check it on every call), but for most functions - even basic functions - you can't check anything. Even something like sqrt can't be checked, because you'd need to know what the input was, which out blocks don't have access to (and really can't have access to in the general case - e.g. an input range can't be saved, and it would be mutated as part of the function's operations). And even if you did have the input, to check whether the output was correct, you'd have to have some sort of simple test based solely on the input that told you whether the input was correct, and in many cases, that would basically mean reimplementing the function. In my experience, unit tests are far more valuable than any assertions inside of a function could be for verifying that a function's output is correct.the function exits, but in the vast majority of cases, what you're testing with an out contract is what unit tests would be testing, in which case, the out blocks don't really add anything, and since they're forced to be general, you can't test for specific results like you can with a unit test.That would be true if: - the unit test was doing exhaustive testing - the unit test is fully specified - the unit test is proven correctBut post conditions that are part of a specification can in theory be used for optimization when you link object files from different sources. So you can change the implementation of one object file with only linking as long as the specification itself does not change. Well, if you had a separate specification...Right there. That's the problem. People keep coming up with ideas about how in blocks and out blocks could _theoretically_ be useful. But as it stands, there's nothing special about them at all, and the fact that D can use separate compilation tends to kill most suggestions of actually doing anything special with them. So, as it stands, in and out blocks do _nothing_ special outside of virtual functions, and they're very noisy visually, making them a huge detractor. So, personally, I don't think that they should be used outside of virtual functions. All of the supposed benefits are theoretical and don't seem likely at all to materialize any time soon - if ever. - Jonathan M Davis
Feb 05 2015
On Thursday, 5 February 2015 at 08:37:07 UTC, Jonathan M Davis wrote:If you're not doing exhaustive unit testing, you're almost certainly doing it wrong.That would be a NP-Hard problem for any function that takes an array as input? :-)And what you _can_ test when a function is exiting without knowing exactly what the input was and what the corresponding output is supposed to be is so minimal to be borderline useless.You know what the input is, that is the point of a postcondition. IF and ONLY IF the precondition holds, then the postcondition holds. Without a postcondition, the precondition is meaningless.Even something like sqrt can't be checked, because you'd need to know what the input wasSure you know. And it is cheap to test too if you have "precondition(isreal(input))" then you get a fully specified "postcondition(output*output==input)". Keep in mind that contracts are for checking interoperability between cohesive units/modules/components. If you have a subcontractor that delivers a probe with a driver then you might want the precondition to be that given input (true,false) you get output in the range <0.0,1.0]. The subcontractor who writes the analytical component will have to make the analyser work for all inputs from the probe in the range <0.0,1.0]. When you scale up then the problem is that people make assumptions about how things work, which they have not implemented themselves. So testing interaction between components may be useful even after deployment. Especially if involves plugins, dynamic loading of code, hardware that is replaced...which out blocks don't have access to (and really can't have access to in the general case - e.g. an input range can't be saved, and it would be mutated as part of the function's operations).That's a D flaw. Not a flaw with pre/postconditions and contracts.And even if you did have the input, to check whether the output was correct, you'd have to have some sort of simple test based solely on the input that told you whether the input was correct, and in many cases, that would basically mean reimplementing the function.No, the interface contract is part of the specification. The implementor has to make an implementation that makes the interface contract checkable if that is part of the deal. Anything less would be a legal contract violation. But the interface contract could be as simple as stating that the input is always in a given range. Then the implementor will only have to check for errors in that range and handle "exceptional situations" that arise within that range in a graceful manner.special outside of virtual functions, and they're very noisy visually, making them a huge detractor. So, personally, I don't thinkThey are noisy and the language and libraries should be improved so that they can be useful for tool writers. But the language should keep the precondition and postcondition together and make them distinct from internal debugging statements. Contracts are meant to be exposed externally. That's a key point that makes them different from asserts.be used outside of virtual functions. All of the supposed benefits are theoretical and don't seem likely at all to materialize any time soon - if ever.It will probably materialize if the language is adopted for large scale projects... Having explicit statements for preconditions and postconditions is useful for code readability. It is just the current syntax that is annoying.
Feb 05 2015
On Thursday, 5 February 2015 at 09:09:32 UTC, Ola Fosheim Grøstad wrote:IF and ONLY IF the precondition holds, then the postcondition holds.Duh, that was wrong... It is only IF, not IFF...
Feb 05 2015
On Wed, 04 Feb 2015 16:24:14 -0800, Andrei Alexandrescu wrote:I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407:=20 auto opSlice(size_t low, size_t high) in { assert(low <=3D high); } body { import std.range : take; return this[low .. $].take(high - low); } =20 which of course trivially boils down to: =20 auto opSlice(size_t low, size_t high) { assert(low <=3D high); import std.range : take; return this[low .. $].take(high - low); } =20 What advantage could possibly be in transforming a 5-liner into a 9-liner? Are we really aiming at writing the maximum possible lines of code here and using as many language features as possible everywhere? =20 I think we should dust off that Phobos contributors' guide. Sadly, there is little we can do against the more subtle issues.so you basically telling that "in block" feature is so useless, that even=20 language devs recommend to avoid it. great.=
Feb 05 2015
On Thursday, 5 February 2015 at 00:24:15 UTC, Andrei Alexandrescu wrote:I'm seeing another idiom that seems to become fashionable. Consider this excerpt from https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm/iteration.d#L407: auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low <= high); import std.range : take; return this[low .. $].take(high - low); } What advantage could possibly be in transforming a 5-liner into a 9-liner? Are we really aiming at writing the maximum possible lines of code here and using as many language features as possible everywhere? I think we should dust off that Phobos contributors' guide. Sadly, there is little we can do against the more subtle issues. Andrei[caveat: I've read some of the posts, yet I don't know, if this has been proposed before in any form] What about moving the contracts somewhere else, like the unittests? auto opSlice(size_t low, size_t high) { import std.range : take; return this[low .. $].take(high - low); } contract { opSlice(size_t low, size_t high) { assert(low <= high); }; sayHello(string str) { assert(str.length); } // ... } Maybe contract functions could be labelled. contract auto opSlice(...) ... Destroy.
Feb 06 2015
On Fri, 06 Feb 2015 14:04:39 +0000, Chris wrote:auto opSlice(size_t low, size_t high)...=20 contract { opSlice(size_t low, size_t high) {dead before the start.=
Feb 06 2015
On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:On Fri, 06 Feb 2015 14:04:39 +0000, Chris wrote:Why? Would you mind to elaborate on that a little? ;)auto opSlice(size_t low, size_t high)...contract { opSlice(size_t low, size_t high) {dead before the start.
Feb 06 2015
On Fri, 06 Feb 2015 15:08:55 +0000, Chris wrote:On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:double declaration is both error-prone and not in D "spirit" ('cause it's=20 error-prone ;-). it also adds alot of noise (imagine template declaration=20 with complex constraints).=On Fri, 06 Feb 2015 14:04:39 +0000, Chris wrote:=20 Why? Would you mind to elaborate on that a little? ;)auto opSlice(size_t low, size_t high)...=20 contract { opSlice(size_t low, size_t high) {dead before the start.
Feb 06 2015
On Fri, 06 Feb 2015 15:08:55 +0000, Chris wrote:On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:p.s. and people will avoid using features that involves heavily copy- pasting, and has no error protection (imagine overloaded functions). so=20 in this form it will be the feature that people will mark as "existent",=20 but will not use, 'cause it's not comfortable enough.=On Fri, 06 Feb 2015 14:04:39 +0000, Chris wrote:=20 Why? Would you mind to elaborate on that a little? ;)auto opSlice(size_t low, size_t high)...=20 contract { opSlice(size_t low, size_t high) {dead before the start.
Feb 06 2015
On Friday, 6 February 2015 at 15:43:42 UTC, ketmar wrote:On Fri, 06 Feb 2015 15:08:55 +0000, Chris wrote:Hm. But the compiler can check, if the signature is ok. E.g. contract auto opSlice(size_t low, size_t high) { return bla; } contract { opSlice(size_t low, size_t high) { assert(low < high); } opSlice(int low, int high) { // <--- Error } } or contract { auto opSlice(size_t low, size_t high) { // Implementation } // contract assert (low < high); } Dunno. I like it, if things can be put aside in blocks, like unittest or debug.On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:p.s. and people will avoid using features that involves heavily copy- pasting, and has no error protection (imagine overloaded functions). so in this form it will be the feature that people will mark as "existent", but will not use, 'cause it's not comfortable enough.On Fri, 06 Feb 2015 14:04:39 +0000, Chris wrote:Why? Would you mind to elaborate on that a little? ;)auto opSlice(size_t low, size_t high)...contract { opSlice(size_t low, size_t high) {dead before the start.
Feb 06 2015
On Fri, 06 Feb 2015 15:59:04 +0000, Chris wrote:Hm. But the compiler can check, if the signature is ok. E.g."wtf, compiler, are you making fun of me? you KNOW what i mean, yet you=20 insisting that i have to please you... ah, fsck it! that shitty feature=20 never worth it anyway." auto foo (int n) { ... } auto foo (int n, int m) { ... } // i'm soooo sleepy contract { auto foo (int n) { ... } auto foo (int n, int m) { ...check for foo(n) that i copipasted here ...and completely forgot about it, 'cause ...that "contract" clause is sooooo far away ...from the function itself... } } and so on.I like it, if things can be put aside in blocks, like=20 unittest or debug.unittest and debug blocks are not parts of function contract, that's why=20 they can be separated. they are merely *checks*, not *prerequisites*.=
Feb 06 2015
On Friday, 6 February 2015 at 16:22:00 UTC, ketmar wrote:On Fri, 06 Feb 2015 15:59:04 +0000, Chris wrote:I would like to try, if it is really so bad. If laziness is an argument against it, it also applies to in {} and out {}, doesn't it?Hm. But the compiler can check, if the signature is ok. E.g."wtf, compiler, are you making fun of me? you KNOW what i mean, yet you insisting that i have to please you... ah, fsck it! that shitty feature never worth it anyway." auto foo (int n) { ... } auto foo (int n, int m) { ... } // i'm soooo sleepy contract { auto foo (int n) { ... } auto foo (int n, int m) { ...check for foo(n) that i copipasted here ...and completely forgot about it, 'cause ...that "contract" clause is sooooo far away ...from the function itself... } } and so on.I like it, if things can be put aside in blocks, like unittest or debug.unittest and debug blocks are not parts of function contract, that's why they can be separated. they are merely *checks*, not *prerequisites*.
Feb 06 2015
On Fri, 06 Feb 2015 19:09:47 +0000, Chris wrote:I would like to try, if it is really so bad. If laziness is an argument against it, it also applies to in {} and out {}, doesn't it?it's not lazyness per se, it's inconsistency and lack of usability. sure,=20 you are free to try, but i bet that you simply waste some time with it. i=20 have nothing personal against this (i simply don't care).=
Feb 06 2015