DIP 1009--Improve Contract Usability--Preliminary Review Round 1

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Tue Jun 20 14:04:16 PDT 2017


On 6/20/17 1:42 PM, H. S. Teoh via Digitalmars-d wrote:
> On Tue, Jun 20, 2017 at 11:57:55AM +0000, Mike Parker via Digitalmars-d wrote:
>> DIP 1009 is titled "Improve Contract Usability".
>>
>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1009.md
> [...]
> 
> What would a body-less declaration of a function look like under the new
> syntax? Hopefully not this:
> 
> 	int myFunc(Args...)(Args args)
> 	if (Args.length > 2)
> 	in assert(args[0] != 0);	// semicolon: ouch
> 	in assert(args[1] > 1);		// semicolon: ouch
> 	// How do we end the declaration here? Another semicolon?
> 	;	// ouch
> 
> Having several semicolons outside a braced block makes declarations
> harder to parse. External tools will no longer be able to just scan for
> top-level semicolons to find the end of the declaration, but will have
> to understand contract syntax too, even if that particular tool doesn't
> care about contracts.
> 
> It gets worse if your contract involves calling another function; you'll
> end up with:
> 
> 	int myFunc(Args...)(Args args)
> 	if (Args.length > 2)
> 	in assert(args[0] != 0); // is this the end of the declaration?
> 	in otherFunc(args[0]);	// is this declaring another function?
> 				// (i.e., a typo of int -> in?)
> 	;	// ouch
> 
> Also, I don't like the idea of putting contracts inside the function
> body. As the DIP already mentions, this makes parsing of contracts more
> difficult. It also causes cognitive dissonance (contracts are a part of
> the function's signature, not its implementation).
> 
> It's even worse if you allow contracts in arbitrary places inside the
> function body -- then even somebody reading the code wouldn't know, at a
> glance, what the contracts are, without scanning the entire function
> body! That makes contracts *harder* to read and use, rather than easier,
> in direct contradiction of the purpose of this DIP.
> 
> 
> Here's my counter-proposal: since the sig constraint line uses
> parentheses (and yes, I deliberately planted a sig constraint above just
> to make this point), why not go for syntactical symmetry? I.e., like
> this:
> 
> 	int myFunc(Args...)(Args args)
> 	if (Args.length > 2)
> 	in (args[0] != 0)
> 	in (args[1] > 1);	// one semicolon to end them all

This is much much better. The verbosity of contracts isn't really the 
brace, it's the asserts. This also gives the compiler a better handle on 
what causes the thing to fail (better error message).

Note that you NEED the semicolon for the DIP's proposal, because `in` is 
also a binary operator, and could be misinterpreted. With yours, it's 
not possible to misinterpret.

> For out-contracts, we could use the existing lambda syntax to avoid the
> ugliness of having two parenthesized expressions next to each other:
> 
> 	// Body-less declaration
> 	int myFunc(Args...)(Args args)
> 	if (Args.length > 1)
> 	in (args[0] > 0)
> 	out (result => result > 10);
> 	// N.B.: instead of: `out(result)(result > 10)` which is uglier.
> 
> 	// Full declaration
> 	int myFunc(Args...)(Args args)
> 	if (Args.length > 1)
> 	in (args[0] > 0)
> 	out (result => result > 10)
> 	{
> 		... // function body goes here
> 	}

I'm not understanding that last part. Current syntax would be:

out(result)
{
    // check result
}

I'm concerned this would be ambiguous with the current syntax.

IMO, this whole proposal doesn't carry enough weight, either your 
version or the DIP itself. I would not be in favor. Current syntax is 
understandable, and not too verbose IMO.

-Steve


More information about the Digitalmars-d mailing list