June 21, 2017
On Wednesday, 21 June 2017 at 13:24:24 UTC, MysticZach wrote:
>
> So weird how this discussion is happening in parallel with this other discussion :-) :
>
> http://forum.dlang.org/post/rkdpuuggltowhqmcmmke@forum.dlang.org

It is, though as I have pointer out over there, I would really like to decouple assert semantics from the new contract semantics to achieve the maximum elegance we can within the design limits of the language.
June 21, 2017
On 21.06.2017 02:51, MysticZach wrote:
> 
> I think people could get used to the cognitive dissonance.

That's really not what D is about.

> I've already gotten used to it just by writing this DIP.

I think it is likely that you are an outlier.

> If such an alternative checking system is utilized,

If so, there should be a way to hook into the checking logic. This has nothing at all to do with contract syntax. asserts and contracts are coupled already, as in-contracts form a disjunction on override by catching AssertErrors.

> the syntax for  writing contracts should be as easy
> for them as for those using `assert`. 

Maybe, but your DIP does not pull its own weight as long as the latter syntax is not a notable improvement over what we have now. H. S. Teoh's counter-proposal is, and I think your DIP has a much higher chance of acceptance if you go with it.
June 21, 2017
On Wednesday, 21 June 2017 at 14:22:52 UTC, Moritz Maxeiner wrote:
>> If you do accidentally forget the extra set of parens on the `out` contract, you would get "Error: `do` expected before function body after a bracketed `out` contract" at the end of the function.
>>
>> (If, however, it a happens to be a nested function, and the next statement in that function happens to be `do`, then the parser will think the `do` loop is the function body... Mmmm, is this worth worrying about??)
>
> Could you give a specific (short) example of what you think of?
> I don't see any potential for ambiguity in the following at a quick glance, so I'm not sure I got where you think the problem lies:
>
> ---
> void foo()
> {
>     int bar(Args...)(Args args)
>       if (Args.length > 2)
>       in (args[0] != 0)
>       in (args[1] > 1)
>       out (result)(result > 0) { ... }
>     do {} while (true);
> }
> ---

The only problem is if a programmer forgets to add the additional parentheses, in which case the bracketed block is then mistaken for the `out` contract, which will lead to a confusing error message. For example:

void foo()
{
   int bar(Args...)(Args args)
      if (Args.length > 2)
      in (args[0] != 0)
      in (args[1] > 1)
      out /*whoops, forgot `( )`*/(result) { ... }

   do { ... }
   while (true); // Error: while statement cannot contain just `;`
}

Honestly this doesn't seem like a big deal, as I'd imagine it'd be hard not to notice that code like this wasn't working as expected. And also extremely rare. So I'm still in favor.

June 21, 2017
On Wednesday, 21 June 2017 at 14:49:09 UTC, Moritz Maxeiner wrote:
> On Wednesday, 21 June 2017 at 13:24:24 UTC, MysticZach wrote:
>>
>> So weird how this discussion is happening in parallel with this other discussion :-) :
>>
>> http://forum.dlang.org/post/rkdpuuggltowhqmcmmke@forum.dlang.org
>
> It is, though as I have pointer out over there, I would really like to decouple assert semantics from the new contract semantics to achieve the maximum elegance we can within the design limits of the language.

Well I'd be just as happy expanding the design limits of the language, i.e. `assert`, if that were a better option. The issue you raise is just how different are `in` and `out` contracts from regular `assert` contracts. They _are_ all listed in the same section of the documentation [1], for whatever that's worth.

The practical question is whether one can assume that the same semantics used for `assert`, whatever they may be, will in all cases be desirable for `in` and `out` too. The flexibility of decoupling them is one solution, if they are clearly sufficiently different. But another option is simply to upgrade `assert` to make sure it offers what everyone wants. I don't know what to suggest, because I don't if `assert` can be made good enough to warrant direct inclusion into the grammar. If it could, then all contracts, including plain `assert` statements, would benefit from them.

[1] https://dlang.org/spec/contracts.html
June 21, 2017
On Wednesday, 21 June 2017 at 16:23:53 UTC, MysticZach wrote:
> void foo()
> {
>    int bar(Args...)(Args args)
>       if (Args.length > 2)
>       in (args[0] != 0)
>       in (args[1] > 1)
>       out /*whoops, forgot `( )`*/(result) { ... }
>
>    do { ... }
>    while (true); // Error: while statement cannot contain just `;`
> }
>
> Honestly this doesn't seem like a big deal, as I'd imagine it'd be hard not to notice that code like this wasn't working as expected. And also extremely rare. So I'm still in favor.

I see. Well, I would only see that as an issue if it would compile and then generate code that differs from what one intended. But since it errors out, I don't see a problem, either, though it would be best to enhance that error message to give a hint that the programmer may have triggered that ambiguous case by accident. Something like "Did you mean `out() (result)`?"
June 21, 2017
On Wednesday, 21 June 2017 at 16:52:24 UTC, MysticZach wrote:
>
> Well I'd be just as happy expanding the design limits of the language, i.e. `assert`, if that were a better option. The issue you raise is just how different are `in` and `out` contracts from regular `assert` contracts.

Well, a contract is an abstraction, asserts are just one possible implementation; so yeah, they are different things.
Technically in the current (verbose) syntax, the `assert` just happen to be part of the contract's implementation; it could really be just anything, including `in { if (!cond) throw Exception }`.

> They _are_ all listed in the same section of the documentation [1], for whatever that's worth.

Well, yeah, because assert's are the most common contract implementation in D.

>
> The practical question is whether one can assume that the same semantics used for `assert`, whatever they may be, will in all cases be desirable for `in` and `out` too. The flexibility of decoupling them is one solution, if they are clearly sufficiently different.

They are (see abstraction vs implementation argument above). We can just as well use another implementation in the new syntax and then we don't have to worry about asserts semantics possibly changing in the future anymore. Also, people arguing for changes in assert semantics don't have to care about contracts if they don't also do DbC. I think decoupling is the way to go here.

> But another option is simply to upgrade `assert` to make sure it offers what everyone wants.

That would be really cool, but I doubt it will be feasible here. I think that in this case it will more likely end up with everyone hating that universal solution equally.

> I don't know what to suggest, because I don't if `assert` can be made good enough to warrant direct inclusion into the grammar. If it could, then all contracts, including plain `assert` statements, would benefit from them.

Well, for me it would be this:
- The compact syntax with `in (cond)` and `out (ident)(cond)`
- Don't lower those contracts directly to any fixed implementation; lower them to a template (similar to what I posted) that you stick in druntime instead
- Allow configuring the template's checking semantics via D versions (you can still then have one implementation choice in the template be asserts, if you want, though I would go with a more riguruous kill switch such as the one I posted)

I would definitely be interested in helping out with the template implementation for druntime, btw.
June 21, 2017
On Wednesday, 21 June 2017 at 15:18:21 UTC, Timon Gehr wrote:
> On 21.06.2017 02:51, MysticZach wrote:
>> 
>> I think people could get used to the cognitive dissonance.
>
> That's really not what D is about.

My counterargument to that is that it's possible that the cognitive dissonance only occurs because of what people are used to, rather than what is inherent to the syntax.

>> I've already gotten used to it just by writing this DIP.
>
> I think it is likely that you are an outlier.

Well my impression was that Walter liked it too, although I could have misinterpreted his comment here:

http://forum.dlang.org/post/ogvt66$1bcp$1@digitalmars.com

>> If such an alternative checking system is utilized,
>
> If so, there should be a way to hook into the checking logic. This has nothing at all to do with contract syntax. asserts and contracts are coupled already, as in-contracts form a disjunction on override by catching AssertErrors.

Improving the checking logic interface may solve at a higher level the problem I'm trying to solve at a very low one, with mere syntax changes, and it might be (is probably?) the best way forward.

>> the syntax for  writing contracts should be as easy
>> for them as for those using `assert`.
>
> Maybe, but your DIP does not pull its own weight as long as the latter syntax is not a notable improvement over what we have now.

Well, my view is that my DIP is actually a very lightweight syntax change, and an equally lightweight improvement in contract syntax, so it's a lost-cost, mild improvement . The cognitive dissonance argument is the main one against it, and I really don't know if that dissonance is based on fundamental flaws in the way I'm thinking about it, or just the "Shock of the New" [1]. If allowing contracts in the function body really is a fundamentally flawed concept, then I won't keep advocating for it.

> H. S. Teoh's counter-proposal is, and I think your DIP has a much higher chance of acceptance if you go with it.

I'm not actually worried about whether the proposal is accepted or not, as long the best ideas and arguments come forward and are heard. I have more faith in the process than I do in any particular proposal.

As far as Teoh's proposal, I would say that its quality is highly correlated to the percentage of projects that find built-in `assert` adequate to their needs, which is hard to assess precisely - the better `assert` is, or can be made to be, the better Teoh's proposal is, I'd say. Moritz [2] suggests solving the problem by decoupling `in` and `out` contract syntax from the checking logic. This seems like a good way to go too. But I'd like to see a little more justification for it.

[1] Robert Hughes documentary, "The Shock of the New" https://www.youtube.com/watch?v=J3ne7Udaetg
[2] http://forum.dlang.org/post/uzzwmgqoqxuxhusjvlcg@forum.dlang.org
June 21, 2017
On Wednesday, 21 June 2017 at 17:38:02 UTC, Moritz Maxeiner wrote:
>> But another option is simply to upgrade `assert` to make sure it offers what everyone wants.
>
> That would be really cool, but I doubt it will be feasible here. I think that in this case it will more likely end up with everyone hating that universal solution equally.

Well the universal solution could be, for example, the suggestions from my post in the other thread:

3. Allow an additional compiler flag for more informative, but heavier asserts, e.g. `-release=informativeAsserts`.

 4. Allow a pragma in the code, e.g. `pragma(asserts, none/regular/informative)` for what kinds of asserts are to be used at a given moment.

This would be added flexibility, rather than a one-size-fits-all solution. So the word "universal" is a little deceptive. The options could also include a user-defined hook for assert.

Question: If `assert` itself allowed a user-defined hook, what would the remaining justification be for decoupling `in` and `out` contracts from the `assert` logic?

That's what I mean by thinking the problem might be fixable by upgrading `assert`.
June 21, 2017
On Wednesday, 21 June 2017 at 17:38:02 UTC, Moritz Maxeiner wrote:
>
> Well, for me it would be this:
> - The compact syntax with `in (cond)` and `out (ident)(cond)`
> - Don't lower those contracts directly to any fixed implementation; lower them to a template (similar to what I posted) that you stick in druntime instead
> - Allow configuring the template's checking semantics via D versions (you can still then have one implementation choice in the template be asserts, if you want, though I would go with a more riguruous kill switch such as the one I posted)
>
> I would definitely be interested in helping out with the template implementation for druntime, btw.

I think this should be taken even further and follow the footsteps of std.experimental.allocator (being thus consistent with what's becoming idiomatic D):

- Introduce the abstract concept of an Allocator analogue called "Insister", which can provide DbI-detectable "insist" functions (e.g. for in contracts, for out contracts, etc.)
- Introduce an interface like IInsister akin to IAllocator, with insisterObject akin to allocatorObject
- Create a thread-local `IInsister theInsister` that can be swapped out at will
- Lower contracts to calls to `theInsister.insist(...)`
- Create some Insister implementations and load theInsister up with one that uses `assert` semantics
June 21, 2017
On Wednesday, 21 June 2017 at 17:55:05 UTC, MysticZach wrote:
>
> This would be added flexibility, rather than a one-size-fits-all solution. So the word "universal" is a little deceptive. The options could also include a user-defined hook for assert.
>
> Question: If `assert` itself allowed a user-defined hook, what would the remaining justification be for decoupling `in` and `out` contracts from the `assert` logic?

Because then you won't have normal asserts and contracts be subject to different semantics?
If I use a library, I may very well want to disable the library's internal assert checks (because I have enough experience that it's working properly), but keep it's contracts alive, because my code is still shiny new and riddled with bugs.