June 28, 2017
On Tuesday, 27 June 2017 at 09:18:11 UTC, Olivier FAURE wrote:
> A bit late to the party, but I would recommend the following syntax:
>
>     out (void; myTest)
>
> for argument-less tests. A casual reader would be less likely to see this in code and think it's some sort of typo; it would be easier to google; and it would make some semantic sense (functions that don't return anything return void).

It's a creative suggestion, and not a bad one. But it's verbose, and I'd like to be able to omit the identifier altogether. Currently, only `for` loops allow this, as when people write:

for( ; ; )

Theoretically, `foreach

foreach( ; a) ...
out( ; ...)

Currently `foreach` does not allow omitting
June 28, 2017
On Wednesday, 28 June 2017 at 01:23:18 UTC, MysticZach wrote:
> On Tuesday, 27 June 2017 at 09:18:11 UTC, Olivier FAURE wrote:
>> A bit late to the party, but I would recommend the following syntax:
>>
>>     out (void; myTest)
>>
>> for argument-less tests. A casual reader would be less likely to see this in code and think it's some sort of typo; it would be easier to google; and it would make some semantic sense (functions that don't return anything return void).
>
> It's a creative suggestion, and not a bad one. But it's verbose, and I'd like to be able to omit the identifier altogether. Currently, only `for` loops allow this, as when people write:
>
> for( ; ; )
>
> Theoretically, `foreach
>
> foreach( ; a) ...
> out( ; ...)
>
> Currently `foreach` does not allow omitting

Sorry, clicked the `send` button too soon.

Anyway, currently `foreach` does not allow omitting the initial identifier, but in theory it _could_ be enhanced to do so. If `out` expressions also allow this, then we get the desired symmetry between `for`,`foreach`, and `out` expressions, with minimal verbosity. That's the solution I promote. It's better than requiring something to be there when nothing really has to be. I don't know why `foreach` isn't already this way.
June 28, 2017
On Sunday, 25 June 2017 at 17:20:51 UTC, Timon Gehr wrote:
> On 25.06.2017 17:46, Petar Kirov [ZombineDev] wrote:
>> On Sunday, 25 June 2017 at 12:10:02 UTC, Timon Gehr wrote:
>>> On 25.06.2017 13:37, Andrei Alexandrescu wrote:
>>> out(result){ assert(result > 0); } // exists
>>>
>>> out result => assert(result > 0) // more of the same
>>>
>>> out(result; result > 0) // better
>> 
>> out result => result > 0 // not much worse
>
> out(result; result > 0, "worse enough")
>
> Also, what Guillaume said.

Why do we need to name the result at all?

Any conflicts with using
`out(out > 0, "message")`
or
`out(return > 0, "message")`?
Or even
`out(someCond($), "message")`?

So using either `out` or `return` or `$` or whatever to always refer to the return value of the function. Just something that's already relevant and used instead of `__result`.

This could even be naturally extended to having an implicitly declared 'result' variable for functions (which could help in optimizations maybe? Something like always having NRVO possible) called `out` or `return`.

R foo(Args...)(Args args) {
    out(return > bar && ensured(return), "foo() fudged its return");
    // ...
    return = blah;
    // ...
    return.quux(var);
    static assert(is(typeof(return) == R)); // of course; this's old syntax
}
June 28, 2017
On Wednesday, 28 June 2017 at 12:17:36 UTC, Enamex wrote:
> Why do we need to name the result at all?
>
> Any conflicts with using
> `out(out > 0, "message")`

No conflict AFAICT. I personally don't like it, though.

> `out(return > 0, "message")`?

Yes, see [1]

> `out(someCond($), "message")`?

Overloading symbols with context dependent meaning is one more step into obfuscation.

> So using either `out` or `return` or `$` or whatever to always refer to the return value of the function. Just something that's already relevant and used instead of `__result`.

Well, `__result` is already implemented and usable, so I would argue it is thus relevant.

> R foo(Args...)(Args args) {
>     out(return > bar && ensured(return), "foo() fudged its return");

Contracts inside function bodies should not be allowed imho.

[1] http://forum.dlang.org/post/oihbot$134s$1@digitalmars.com
June 28, 2017
On Wednesday, 28 June 2017 at 12:34:59 UTC, Moritz Maxeiner wrote:
> On Wednesday, 28 June 2017 at 12:17:36 UTC, Enamex wrote:
>> `out(return > 0, "message")`?
>
> Yes, see [1]

It has the already used `typeof(return)` going for it, though.

A big point against it IMO would be its moving further from `return`'s
signal that a function scope is exited at that line (instead it could
be a variable assignment which is meh (usage in a contract check is OK
since we're already outside the function)).

>> `out(someCond($), "message")`?
>
> Overloading symbols with context dependent meaning is one more step into obfuscation.

True.

>> So using either `out` or `return` or `$` or whatever to always refer to the return value of the function. Just something that's already relevant and used instead of `__result`.
>
> Well, `__result` is already implemented and usable, so I would argue it is thus relevant.

It's not used in the wild yet though :T

>> R foo(Args...)(Args args) {
>>     out(return > bar && ensured(return), "foo() fudged its return");
>
> Contracts inside function bodies should not be allowed imho.
>
> [1] http://forum.dlang.org/post/oihbot$134s$1@digitalmars.com

I was going with the current 'Proposal' syntax in the DIP's document. There
a more recent proposal here?
June 28, 2017
On Wednesday, 28 June 2017 at 14:09:40 UTC, Enamex wrote:
> On Wednesday, 28 June 2017 at 12:34:59 UTC, Moritz Maxeiner wrote:
>> On Wednesday, 28 June 2017 at 12:17:36 UTC, Enamex wrote:
>>> R foo(Args...)(Args args) {
>>>     out(return > bar && ensured(return), "foo() fudged its return");
>>
>> Contracts inside function bodies should not be allowed imho.
>
> I was going with the current 'Proposal' syntax in the DIP's document. There a more recent proposal here?

The DIP is still at pre-preliminary review round 1 (since it hasn't finished yet).
The current syntax proposal is effectively emergent through H. S. Teoh's general proposal [1], Solomon E's out enhancement [2], and Timon Gehr's implementation of the former two [3].
You can see in Timon's examples [4] how it looks (and contracts are part of a function's signature).

[1] http://forum.dlang.org/post/mailman.3511.1497981037.31550.digitalmars-d@puremagic.com
[2] http://forum.dlang.org/post/xtimtynqeuzmgaychpdq@forum.dlang.org
[3] http://forum.dlang.org/post/oijl5f$20fv$1@digitalmars.com
[4] https://github.com/dlang/dmd/compare/master...tgehr:contract-syntax#diff-0630cf91becfdb077688ebd1ef400c5a
June 28, 2017
On Wednesday, 28 June 2017 at 14:09:40 UTC, Enamex wrote:
>
> It has the already used `typeof(return)` going for it, though.
>

That's why I had suggested it above. However, I think the point they raised about parsing in response was a good one.
June 28, 2017
On Wednesday, 28 June 2017 at 14:33:52 UTC, Moritz Maxeiner wrote:
> The DIP is still at pre-preliminary review round 1 (since it hasn't finished yet).
> The current syntax proposal is effectively emergent through H. S. Teoh's general proposal [1], Solomon E's out enhancement [2], and Timon Gehr's implementation of the former two [3].
> You can see in Timon's examples [4] how it looks (and contracts are part of a function's signature).

Yes, this thread has been incredibly productive, and has resulted in a complete metamorphosis of my original proposal, into a proposal that I think is very strong. I have to rewrite the existing DIP to reflect that.
June 29, 2017
On Tuesday, 27 June 2017 at 23:17:15 UTC, Moritz Maxeiner wrote:
> Considering that code is read a lot more than written those two are *critically* important.
> What more do you expect? It could eventually be optimized to inject the in contract check at the caller's side (before entering the function), but the point of contracts is that they *aren't* violated. If they are, well, your program[1] is broken and needs to die.
>
> [1] abstract: computational task; implementation barring safe thread/fiber killing: process

Sure, but it would be even better if it hadn't compiled in the first place. For instance, the "pure" attribute is a sort of contract, and if a function designated "pure" modifies global state then my code *does not compile*. Furthermore, if a pure function foo() contains a call to a function bar() not designated "pure", then it doesn't compile either, even though bar() may in fact be pure. So the compiler's behavior is "I can't guarentee that this function is pure, therefore I refuse to compile". In other words, I get useful error-checking from the compiler at the cost of having to "help" him a bit from time to time (like designating bar() as pure in this example).

The above behavior is unreasonable for validating a completely general contract - the compiler won't be able to guarentee much without excessive effort on the part of the programmer, supplying it with informative preconditions and postconditions. Nevertheless, as attributes like pure, const, safe and nogc demonstrate, the compiler can be of great help in writing correct code. Detecting violations of these function attributes in run-time is trivial but far less useful.

So basically, I'd like the ability to implement fairly simple contracts (with a similar level of sophistication to the above examples) that the compiler can check for me. I don't know, maybe this is easier to implement using UDAs...
June 28, 2017
On Thu, Jun 29, 2017 at 01:22:31AM +0000, Mark via Digitalmars-d wrote: [...]
> So basically, I'd like the ability to implement fairly simple contracts (with a similar level of sophistication to the above examples) that the compiler can check for me. I don't know, maybe this is easier to implement using UDAs...

One idea I have is that the compiler could recognize certain straightforward contracts (like int < value) and use VRP (value range propagation) to detect cases where it's clear that the contract would be violated.

However, this can only be done in a very rudimentary fashion, because:

(1) DbC contracts pertain to *runtime* argument values, so while
checking for simple cases at compile-time is nice, it isn't really in
the charter of (D's implementation of) DbC.

(2) VRP in the compiler currently only works within a very limited
scope, IIRC within a single expression. So while it may detect the
`foo(bar())` case, it probably won't detect the `x=bar(); foo(x);` case.
Ostensibly the scope of VRP ought to be expanded, however:

(3) In the past Walter has shown some reluctance in adding features that hurt compilation time; if a more sophisticated implementation of VRP is required and it's deemed too expensive in terms of compilation time, Walter may veto it.

(4) Arbitrarily complex boolean conditions are undecidable in general, so unless you have a way to solve the halting problem, a general solution is intractible.  Of course, the kind of conditions you find in contracts generally ought to be nowhere near the halting problem in complexity, but it's not clear how far one can go without running the risk of (3).  My guess is that something based on VRP is the most likely to materialize in the foreseeable future.


T

-- 
First Rule of History: History doesn't repeat itself -- historians merely repeat each other.