an old topic (pun intended)

Davidson Corry davidsoncorry at comcast.net
Wed Oct 26 22:58:25 PDT 2011


On 10/26/2011 5:19 PM, bearophile wrote:
>>       out(result, X preX = exprX, Y preY = exprY) {   //<== prestate
> I'd like something lighter, syntax-wise, where the is no need to state new and old names and types:
>
>> >        out(result, exprX, exprY) {
> And then the compiler lets you access in the postcondition the old variables in some standard way, like:
>
> in.exprX, in.exprY
>
> Despite this is is probably better looking:
>
> old.exprX, old.exprY

I had intended for 'exprX' to represent some complex expression, not 
simply a symbol. For instance, what if the prestate that you want to 
capture is not merely the value-at-entry of some single datum, but 
rather a "meta-prestate" computed from multiple source data?

For instance, suppose that you were generating hash functions and keys 
for a cryptographic encoder class, and you had a function 
figure_of_merit() [NOT a member of the class] that produces some metric 
for how well the encryption works, based on the results of encrypting 
each element of an array of sample plain-texts, and analyzing the 
cryptexts thus produced.

The encoder class has data members 'internalKey' (a string used to 
decode the encrypted text) and 'internalHashDelegate' (a delegate to a 
hash-generating function which the class uses to encrypt plaintexts).

The class also has a function generate_improved_hash_and_key() which 
potentially modifies either 'internalKey' or 'internalHashDelegate' or 
both, and you would like to verify that the function actually does 
improve things, or at least not make them worse:

	void generate_improved_hash_and_key(string[] plaintexts)
	out (float preFOM = figure_of_merit(plaintexts, internalKey, 
internalHashDelegate) ) {
		assert(preFOM <= figure_of_merit(plaintexts, internalKey, 
internalHashDelegate);
	}
	body { /* ... */ }

I cannot see that the expression

	old.figure_of_merit(plaintexts, internalKey, internalHashDelegate)

is an improvement over  'preFOM'.

It's also not easy for the compiler to figure out that, in the 
old.expression, the arguments 'internalKey' and 'internalHashDelegate' 
are the values of those data at entry-to-function, and somehow need to 
be cached out to be used in the post-condition comparison, while the 
very same arguments to the figure_of_merit() function in the body of the 
post-condition are the values at the END of the function's execution.

With the syntax I proposed, the compiler doesn't have to figure out 
either: the expression in the out(...) argument list gets injected at 
the very start of the function body, and evaluates based on the 
conditions BEFORE the function body gets going, while the body of the 
post-condition is conceptually injected at the very end of the function 
body [as if in a scope(exit) block] and uses the conditions that hold 
AFTER the function body has completed execution.

> Here "old" doesn't need to be keyword, it's like the local name of a struct instance.
> As discussed in D.learn there is no need for deep copying of the old variables. If it's required, then the programmer has to do it manually by herself. This avoids lot of implementation complexities.

Agreed. As in Eiffel, the programmer has the freedom, the responsibility 
AND the power to do any deep-copy work needed. For example,

	void foo(A a)
	out (auto preA = a) { /* post-condition body using preA */ }
	body { /* whatever foo() does */ }

would not work because 'preA' is just an additional reference to the 
object that 'a' also refers to. If foo() happened to modify 
'a.some_member', by data aliasing it has also modified 
'preA.some_member', so the actual prestate is lost.

You would have to do one of the following:
	out (auto preA = a.dup)
	out (immutable(A) preA = a)
or use a struct for A with postblit constructor as needed (value 
semantics rather than reference semantics).

Or drill down into the 'a' object and capture just the internal members, 
or expressions built from them, that you need. It's up to you. And you 
have the full power of the language to do it with.

-- Davidson



More information about the Digitalmars-d mailing list