June 22, 2017
On 6/22/17 5:56 PM, Timon Gehr wrote:
> On 22.06.2017 23:51, MysticZach wrote:
>> On Thursday, 22 June 2017 at 21:41:55 UTC, MysticZach wrote:
>>>> The whole double parentheses is a bit ugly to me. Is there any problem with
>>>> out(return > 0)
>>>> instead of
>>>> out(r) (r > 0)
>>
>> I'm sorry, I didn't read closely. I think that's just asking for trouble, wanting to use `return` as an identifier. Timon found a specific reason why, but in general contextual keywords are frowned upon for precisely this type of ambiguity in the meaning of the code.
> 
> 
> (It's not a contextual keyword. A contextual keyword is an identifier that is reserved in some contexts but not others.)

We can call that contextual "keyword" result. Doesn't have to be a keyword, just the implied return value symbol name.

It would work fine on it's own. My concern is that out(result > 4) matches the grammar for the declaration (a bit) for the declaration of the out contract today.

If we allow not supplying the body (do) keyword, then it's almost exactly the same. In fact, if you are just asserting the result, then:

int foo()
out(result)
{
}

what does this mean? Does it mean assert(result) on the out contract, or this is the old form of out?

If we didn't have contract syntax already, and many existing code bases that use it, I'd say this would be the way to go.

-Steve
June 23, 2017
On Friday, 23 June 2017 at 00:17:23 UTC, Steven Schveighoffer wrote:
> int foo()
> out(result)
> {
> }
>
> what does this mean? Does it mean assert(result) on the out contract, or this is the old form of out?
>
> If we didn't have contract syntax already, and many existing code bases that use it, I'd say this would be the way to go.

The current grammar is:

OutStatement:
   out ( Identifier ) { Statement }
   out { Statement }

So one way out is simply to demand that there be more than just an identifier when checking in the new way. So you'd have to require more tokens, e.g.`out(result !is null)` instead of just `out(result)` in order for the parser to easily distinguish between the two. It's a little messy. On the other hand, requiring two sets of parens is clean, but ugly. So it's a choice between ugly and messy, unless someone comes up with something more elegant.
June 23, 2017
On Friday, 23 June 2017 at 00:17:23 UTC, Steven Schveighoffer wrote:
> We can call that contextual "keyword" result. Doesn't have to be a keyword, just the implied return value symbol name.

Another problem is that any given contextual reserved identifier you choose will run the risk of shadowing other variables. `result` could easily already be defined in an outer context. A solution to this is to use a variable starting with `__`, as those are the existing way of defining reserved identifiers. Maybe `__result`?


June 23, 2017
On Thursday, 22 June 2017 at 22:12:57 UTC, MysticZach wrote:
> On Thursday, 22 June 2017 at 21:56:29 UTC, Timon Gehr wrote:
>> On 22.06.2017 23:51, MysticZach wrote:
>>> On Thursday, 22 June 2017 at 21:41:55 UTC, MysticZach wrote:
>>>>> The whole double parentheses is a bit ugly to me. Is there any problem with
>>>>> out(return > 0)
>>>>> instead of
>>>>> out(r) (r > 0)
>>> 
>>> I'm sorry, I didn't read closely. I think that's just asking for trouble, wanting to use `return` as an identifier. Timon found a specific reason why, but in general contextual keywords are frowned upon for precisely this type of ambiguity in the meaning of the code.
>>
>>
>> (It's not a contextual keyword. A contextual keyword is an identifier that is reserved in some contexts but not others.)
>
> I would argue that the above suggestion promotes `return` precisely that way. It's now an identifier in precisely that one context, but is reserved as a keyword in all other contexts. Not sure what to call it. But we're a little off topic, as we both agree that the above solution to the double parens isn't viable, right?

It's not an identifier, means syntactically it is still a reserved keyword but you are right that it would be semantically very different. In normal contexts it's a flow control statement in that context it is an alias to a value with no influence of the program flow. Would be really annoyingly contradictory.
June 23, 2017
On Friday, 23 June 2017 at 04:08:39 UTC, MysticZach wrote:
> On Friday, 23 June 2017 at 00:17:23 UTC, Steven Schveighoffer wrote:
>> int foo()
>> out(result)
>> {
>> }
>>
>> what does this mean? Does it mean assert(result) on the out contract, or this is the old form of out?
>>
>> If we didn't have contract syntax already, and many existing code bases that use it, I'd say this would be the way to go.
>
> The current grammar is:
>
> OutStatement:
>    out ( Identifier ) { Statement }
>    out { Statement }
>
> So one way out is simply to demand that there be more than just an identifier when checking in the new way. So you'd have to require more tokens, e.g.`out(result !is null)` instead of just `out(result)` in order for the parser to easily distinguish between the two. It's a little messy. On the other hand, requiring two sets of parens is clean, but ugly. So it's a choice between ugly and messy, unless someone comes up with something more elegant.

What I expected from my impression of existing D syntax was that something like this might be coming up:

T foo(T)(T x, T y)
    in (x > 0, y > 0)
    out (r; r > 0)
{
    return x % y + 1;
}

`out ()` has syntax similar to `foreach` and `for`, allowing mentioning something about the return type, or unpacking a return value, then testing it. (When there's no semicolon, an `out` block follows.)

`in ()` has syntax similar to an initializer for an array of `bool`, so that which condition failed can be given an index for generating error messages.

Not because it's elegant, but because it's complicated. It provides some features that were asked for in this thread and in some comments on DIP 1003, plus more possibilities.

I don't see where this breaks any existing D syntax, but maybe this sort of complication should be reserved for D++.
June 23, 2017
On Friday, 23 June 2017 at 09:06:59 UTC, Solomon E wrote:
> What I expected from my impression of existing D syntax was that something like this might be coming up:
>
> T foo(T)(T x, T y)
>     in (x > 0, y > 0)
>     out (r; r > 0)
> {
>     return x % y + 1;
> }
>
> `out ()` has syntax similar to `foreach` and `for`, allowing mentioning something about the return type, or unpacking a return value, then testing it. (When there's no semicolon, an `out` block follows.)

This is a good idea, and I didn't think of it. Points:

* It would be great if you were allowed to omit the identifier before the semicolon in cases where you didn't need it. The existing foreach grammar does not allow this [1]. I'm not sure if that is intended to prevent bugs, or if it was just never thought to be useful.

* The grammar for what's inside the parens should also mimic what's inside `assert`s, allowing an error message. So the new grammar would actually be a mix of the existing `foreach` and `assert` grammars, e.g.

out(r; r >0, "contract violated!")

Comparing with the double parens solution:

out(result)(result > 0, "violation!")
out()(otherData > 0, "prohibited!")

vs.

out(result; result > 0, "violation!")
out(; otherData > 0, "prohibited!")

It's a close call. Nice job!

[1] https://dlang.org/spec/statement.html#foreach-statement

June 23, 2017
On 6/23/17 5:06 AM, Solomon E wrote:
> What I expected from my impression of existing D syntax was that something like this might be coming up:
> 
> T foo(T)(T x, T y)
>      in (x > 0, y > 0)
>      out (r; r > 0)
> {
>      return x % y + 1;
> }

The out contract looks pretty good actually. The in contract, not as good. That looks like a comma expression. I'd rather see this be:

     in(x > 0)
     in(y > 0)

or

     in(x > 0 && y > 0)

In this case, we have something I think I would support.

-Steve
June 23, 2017
On Friday, 23 June 2017 at 13:00:30 UTC, Steven Schveighoffer wrote:
>
> The out contract looks pretty good actually. The in contract, not as good. That looks like a comma expression. I'd rather see this be:
>
>      in(x > 0)
>      in(y > 0)
>
> or
>
>      in(x > 0 && y > 0)
>
> In this case, we have something I think I would support.
>
> -Steve

I agree.
June 23, 2017
On Friday, 23 June 2017 at 13:26:53 UTC, jmh530 wrote:
> On Friday, 23 June 2017 at 13:00:30 UTC, Steven Schveighoffer wrote:
>>
>> The out contract looks pretty good actually. The in contract, not as good. That looks like a comma expression. I'd rather see this be:
>>
>>      in(x > 0)
>>      in(y > 0)
>>
>> or
>>
>>      in(x > 0 && y > 0)
>>
>> In this case, we have something I think I would support.
>>
>> -Steve
>
> I agree.

Same here: Kudos (!) to Solomon for the out resembling foreach, but I don't support comma separation within in contracts, as it's inconsistent when compared to `&&` and `||`.
Adjusted earlier example:

---
int myFunc(Args...)(Args args)
  if (Args.length > 2)
  in (args[0] != 0, "Yikes!")
  in (args[1] > 1)
  out (result; result > 0, "Oops...")
  out (; globalStateStillValid) { ... }
---

Looks nice and clear to me.

OT: Anyone interested in a DIP for more template constraint unfulfilled information in a consistent way to contracts (?) :
---
int myFunc(Args...)(Args args)
  if (Args.length > 0, "Starving!")
  if (Args.length > 1, "Still hungry!")
  if (Args.length > 2, "Just a little bit more!")
  in (args[0] != 0, "Yikes!")
  in (args[1] > 1, "Why you do this?")
  out (result; result > 0, "Oops...") { ... }
---
June 23, 2017
On Friday, 23 June 2017 at 13:00:30 UTC, Steven Schveighoffer wrote:
> On 6/23/17 5:06 AM, Solomon E wrote:
>> What I expected from my impression of existing D syntax was that something like this might be coming up:
>> 
>> T foo(T)(T x, T y)
>>      in (x > 0, y > 0)
>>      out (r; r > 0)
>> {
>>      return x % y + 1;
>> }
>
> The out contract looks pretty good actually. The in contract, not as good. That looks like a comma expression. I'd rather see this be:
>
>      in(x > 0)
>      in(y > 0)
>
> or
>
>      in(x > 0 && y > 0)

I would assume the grammar for these expressions would be the same as for `assert`s. So you're right in pointing out the flaw above.