August 01, 2017
On Monday, 31 July 2017 at 09:55:22 UTC, Nick Treleaven wrote:
> This is subjective. If you put `do` on the end of the line, it is trivial:
>
> in(x > 4)
> out(works)
> out(r; r.test)
> out(flag) do
> {
>   // body
> }

The common case is for `out` contracts to test for the return variable. Something like 90% will therefore look like:

int fun(int x)
out(r; r > 0)
{

}

So it's the uncommon case we're trying to solve for. Requiring `do` in precisely one case, which is the rare case in which the `out` test has only one identifier, and therefore can't be disambiguated from existing `out` contracts, is a solution to that problem. It's seems like a complicated one. To me, it's simpler to simply require the `;` because it's the uncommon case to begin with, and everyone will know what it means because they'll be used to seeing `out(r; r > 0)`.

That said, `do` can solve the loophole with the alternative ambiguous syntax. For example:

int fun(ref int x, ref int y, ref int z)
out(x)     // fine, followed by another contract
out(y != 0) // fine, multiple tokens, unambiguous
out(z) do   // fine, followed by `do`
{
}

If you forget to add the `do` there is an inevitable parsing error, so it's not that bad even in the worst case. The error can be fixed by changing `out(z)` to `out(z != 0)`, or to `out(z) do` as you suggest. `do` is only going to be valuable in that one case, though. I'd say it depends where the language designers want to pay the cost of solving the problem. Either pay it up front with the ugliness of the foreach syntax, or pay it in complexity with the different cases of the ambiguous syntax. Because it's a programming language and not a sports car, I'd probably  choose the consistency of the foreach syntax over the attractiveness of the ambiguous syntax. But there's no clear winner, IMO.
1 2 3 4
Next ›   Last »