www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Another idiom I wish were gone from phobos/druntime

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
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.


 Andrei
So 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
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/15 4:37 PM, Adam D. Ruppe wrote:
 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)
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. -- Andrei
Feb 04 2015
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
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. -- Andrei
There only a benefit because the coding style for contract is ridiculous. Let's fix the right problem here.
Feb 04 2015
prev sibling next sibling parent reply "Zach the Mystic" <reachzach gggmail.com> writes:
On Thursday, 5 February 2015 at 00:43:04 UTC, Andrei Alexandrescu 
wrote:
 On 2/4/15 4:37 PM, Adam D. Ruppe wrote:
 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)
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. -- Andrei
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?
Feb 04 2015
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
parent "Zach the Mystic" <reachzach gggmail.com> writes:
On Thursday, 5 February 2015 at 05:48:43 UTC, bearophile wrote:
 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
My proposal is just effectively syntax sugar for DbC, which the average programmer (not you!) will actually want to use.
Feb 05 2015
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
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
parent reply "Zach the Mystic" <reachzach gggmail.com> writes:
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:
 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.
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.
Feb 05 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
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
parent reply "Zach the Mystic" <reachzach gggmail.com> writes:
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:
 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
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.
Feb 08 2015
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
parent "Zach the Mystic" <reachzach gggmail.com> writes:
On Sunday, 8 February 2015 at 17:12:20 UTC, Daniel Murphy wrote:
 "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.
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); }
 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
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Wed, 04 Feb 2015 16:43:04 -0800, Andrei Alexandrescu wrote:

 On 2/4/15 4:37 PM, Adam D. Ruppe wrote:
 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)
=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. -- Andrei
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?=
Feb 05 2015
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
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:
 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)
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.
Feb 08 2015
prev sibling next sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
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
            {
                import std.range : take;
                return this[low .. $].take(high - low);
            }
auto opSlice(size_t low, size_t high) in { assert(low <= high); } body { }
Feb 04 2015
prev sibling next sibling parent reply "Jonathan Marler" <johnnymarler gmail.com> writes:
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,
 bearophile
Not 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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/15 4:40 PM, Jonathan Marler wrote:
 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,
 bearophile
Not to mention that contracts can be removed by the compiler at compile time.
Same about asserts. -- Andrei
Feb 04 2015
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu 
wrote:
 On 2/4/15 4:40 PM, Jonathan Marler wrote:
 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,
 bearophile
Not to mention that contracts can be removed by the compiler at compile time.
Same about asserts. -- Andrei
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).
Feb 04 2015
prev sibling parent reply "Jonathan Marler" <johnnymarler gmail.com> writes:
On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu 
wrote:
 On 2/4/15 4:40 PM, Jonathan Marler wrote:
 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,
 bearophile
Not to mention that contracts can be removed by the compiler at compile time.
Same about asserts. -- Andrei
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)
Feb 04 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/15 4:50 PM, Jonathan Marler wrote:
 On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei Alexandrescu wrote:
 On 2/4/15 4:40 PM, Jonathan Marler wrote:
 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,
 bearophile
Not to mention that contracts can be removed by the compiler at compile time.
Same about asserts. -- Andrei
Only if the function is inlined.
Non-debug mode removes asserts statically. -- Andrei
Feb 04 2015
next sibling parent reply "David Nadlinger" <code klickverbot.at> writes:
On Thursday, 5 February 2015 at 01:09:15 UTC, Andrei Alexandrescu 
wrote:
 Non-debug mode removes asserts statically. -- Andrei
Using 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
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:
 Non-debug mode removes asserts statically. -- Andrei
Using pre-/post-conditions allows the _caller_ to specify whether the checks are run without recompiling the function body, at least in theory.
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 Davis
Feb 05 2015
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
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:
 On Thursday, 5 February 2015 at 01:09:15 UTC, Andrei 
 Alexandrescu
 wrote:
 Non-debug mode removes asserts statically. -- Andrei
Using pre-/post-conditions allows the _caller_ to specify whether the checks are run without recompiling the function body, at least in theory.
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
DMD is broken. There is no need to break phobos in addition.
Feb 05 2015
prev sibling parent "Dragos Carp" <dragoscarp gmail.com> writes:
On Thursday, 5 February 2015 at 01:09:15 UTC, Andrei Alexandrescu 
wrote:
 On 2/4/15 4:50 PM, Jonathan Marler wrote:
 On Thursday, 5 February 2015 at 00:42:01 UTC, Andrei 
 Alexandrescu wrote:
 On 2/4/15 4:40 PM, Jonathan Marler wrote:
 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,
 bearophile
Not to mention that contracts can be removed by the compiler at compile time.
Same about asserts. -- Andrei
Only if the function is inlined.
Non-debug mode removes asserts statically. -- Andrei
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-options
Feb 05 2015
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
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
Various 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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
next sibling parent "Jonathan Marler" <johnnymarler gmail.com> writes:
On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu 
wrote:
 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.
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.
Feb 04 2015
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
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
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/15 5:32 PM, deadalnix wrote:
 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.
Yah, I understand the potential there. Consider me grudgingly convinced :o). -- Andrei
Feb 04 2015
parent reply "Meta" <jared771 gmail.com> writes:
On Thursday, 5 February 2015 at 01:33:54 UTC, Andrei Alexandrescu 
wrote:
 On 2/4/15 5:32 PM, deadalnix wrote:
 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.
Yah, I understand the potential there. Consider me grudgingly convinced :o). -- Andrei
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.
Feb 04 2015
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
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
next sibling parent reply "Meta" <jared771 gmail.com> writes:
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 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
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.
Feb 04 2015
parent reply "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
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
parent reply "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Thursday, 5 February 2015 at 06:51:35 UTC, Vlad Levenfeld 
wrote:
 I could care less
Er, stupid but unfortunately common american english idiom. For non-native speakers, I mean to say I could NOT care less.
Feb 04 2015
parent reply "eles" <eles eles.com> writes:
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:
 I could care less
Er, stupid but unfortunately common american english idiom. For
Thanks. I was firmly convinced that's a typo...
Feb 05 2015
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:
 On Thursday, 5 February 2015 at 06:51:35 UTC, Vlad Levenfeld
 wrote:
 I could care less
Er, stupid but unfortunately common american english idiom. For
Thanks. I was firmly convinced that's a typo...
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 Davis
Feb 05 2015
next sibling parent "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
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
prev sibling next sibling parent reply Mike Parker <aldacron gmail.com> writes:
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:
 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:
 I could care less
Er, stupid but unfortunately common american english idiom. For
Thanks. I was firmly convinced that's a typo...
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 Davis
I can't phantom that!
Feb 05 2015
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/5/15 5:47 AM, Mike Parker wrote:
 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:
 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:
 I could care less
Er, stupid but unfortunately common american english idiom. For
Thanks. I was firmly convinced that's a typo...
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 Davis
I can't phantom that!
I think we should return to the topic at hand irregardless. -- Andrei
Feb 05 2015
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
next sibling parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
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:
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"!
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 Morton
Feb 05 2015
prev sibling parent Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:
 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"!
LOL. - Jonathan M Davis
Feb 05 2015
prev sibling parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
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 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
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.
Feb 04 2015
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
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
next sibling parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
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:
 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.
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. - Paulo
Feb 05 2015
parent reply "deadalnix" <deadalnix gmail.com> writes:
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
parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
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:
 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.
I am out.
Feb 05 2015
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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:
 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.
I am out.
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...
Feb 05 2015
parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
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:
 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:
 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.
I am out.
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...
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. -- Paulo
Feb 05 2015
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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_Cut
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. Bye, bearophile
Feb 06 2015
parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
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:
 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.
I am out.
To be frankly brutal, you were never in. You presented no argument.
Feb 05 2015
parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
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:
 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:
 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.
I am out.
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. 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. -- Paulo
Feb 05 2015
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 5 February 2015 at 19:19:43 UTC, Paulo Pinto wrote:
 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.
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.
 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
prev sibling parent reply "eles" <eles eles.com> writes:
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:
 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
Wow. Amazing discussion.
Feb 05 2015
parent reply "eles" <eles eles.com> writes:
On Thursday, 5 February 2015 at 10:51:32 UTC, eles wrote:
 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:
 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
Wow. Amazing discussion.
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.
Feb 05 2015
next sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/5/15 2:55 AM, eles wrote:
 On Thursday, 5 February 2015 at 10:51:32 UTC, eles wrote:
 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:
 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
Wow. Amazing discussion.
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.
It has been preapproved. The challenge now is implementing it. -- Andrei
Feb 05 2015
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/5/15 9:31 AM, Andrei Alexandrescu wrote:
 On 2/5/15 2:55 AM, eles wrote:
 On Thursday, 5 February 2015 at 10:51:32 UTC, eles wrote:
 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:
 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
Wow. Amazing discussion.
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.
It has been preapproved. The challenge now is implementing it. -- Andrei
Better put: it had been preapproved back in Jan 2013 and is still looking for someone to fix it. -- Andrei
Feb 05 2015
prev sibling next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Thursday, 5 February 2015 at 06:41:59 UTC, Daniel Murphy wrote:
 "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.
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.
Feb 05 2015
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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. -- Andrei
Unfortunately 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
prev sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Thursday, February 05, 2015 17:42:11 Daniel Murphy via Digitalmars-d wrote:
 "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.
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 Davis
Feb 05 2015
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:
 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.
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 Davis
Feb 05 2015
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
prev sibling parent reply "Kagamin" <spam here.lot> writes:
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
parent Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:
 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.
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 Davis
Feb 05 2015
prev sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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...
 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.
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 Davis
Feb 05 2015
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
prev sibling parent "Atila Neves" <atila.neves gmail.com> writes:
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:
 On 2/4/15 5:32 PM, deadalnix wrote:
 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.
Yah, I understand the potential there. Consider me grudgingly convinced :o). -- Andrei
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 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. Atila
Feb 05 2015
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/4/2015 5:32 PM, deadalnix wrote:
 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.
I was prepared to argue with you, but you're right on all points. Nicely done. Thanks!
Feb 05 2015
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
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
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
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:
Would introduce an exception to our brace-on-its-line rule.
Which is already blatantly violated everywhere in single-line functions.
 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
next sibling parent reply "Jonathan Marler" <johnnymarler gmail.com> writes:
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.


 T
Ahhh...thanks for this. I've been searching for an eloquent way to say this for a while :)
Feb 04 2015
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/15 6:10 PM, Jonathan Marler wrote:
 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.


 T
Ahhh...thanks for this. I've been searching for an eloquent way to say this for a while :)
Hey, I've been saying that all over https://issues.dlang.org/show_bug.cgi?id=14125 :o). -- Andrei
Feb 04 2015
prev sibling parent Nick Treleaven <ntrel-pub mybtinternet.com> writes:
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:
On Thursday, 5 February 2015 at 01:07:56 UTC, Andrei Alexandrescu wrote:
Would introduce an exception to our brace-on-its-line rule.
Which is already blatantly violated everywhere in single-line functions.
We really should support => syntax for these instead, they are very common. Consistent with lambdas.
Feb 05 2015
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/15 5:34 PM, deadalnix wrote:
 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) ?
As a Facebook fellow, I wouldn't mind Egyptian braces. But they won't happen. -- Andrei
Feb 04 2015
prev sibling parent reply "Kagamin" <spam here.lot> writes:
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:
 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) ?
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); }
Feb 05 2015
parent Nick Treleaven <ntrel-pub mybtinternet.com> writes:
On 05/02/2015 08:56, Kagamin wrote:
 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:
 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) ?
If contracts would support single statements:
+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.
Feb 05 2015
prev sibling next sibling parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
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
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:
 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
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.
 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...
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
parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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 was
Sure 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 think
They 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
parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
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
prev sibling parent reply "Chris" <wendlec tcd.ie> writes:
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
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
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
parent reply "Chris" <wendlec tcd.ie> writes:
On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:
 On Fri, 06 Feb 2015 14:04:39 +0000, Chris wrote:

 auto opSlice(size_t low, size_t high)
...
 
 contract {
    opSlice(size_t low, size_t high) {
dead before the start.
Why? Would you mind to elaborate on that a little? ;)
Feb 06 2015
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 06 Feb 2015 15:08:55 +0000, Chris wrote:

 On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:
 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.
=20 Why? Would you mind to elaborate on that a little? ;)
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).=
Feb 06 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 06 Feb 2015 15:08:55 +0000, Chris wrote:

 On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:
 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.
=20 Why? Would you mind to elaborate on that a little? ;)
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.=
Feb 06 2015
parent reply "Chris" <wendlec tcd.ie> writes:
On Friday, 6 February 2015 at 15:43:42 UTC, ketmar wrote:
 On Fri, 06 Feb 2015 15:08:55 +0000, Chris wrote:

 On Friday, 6 February 2015 at 14:29:16 UTC, ketmar wrote:
 On Fri, 06 Feb 2015 14:04:39 +0000, Chris wrote:

 auto opSlice(size_t low, size_t high)
...
 
 contract {
    opSlice(size_t low, size_t high) {
dead before the start.
Why? Would you mind to elaborate on that a little? ;)
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.
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.
Feb 06 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
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
parent reply "Chris" <wendlec tcd.ie> writes:
On Friday, 6 February 2015 at 16:22:00 UTC, ketmar wrote:
 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 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*.
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?
Feb 06 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
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