Pure Contract bug?
Timon Gehr
timon.gehr at gmx.ch
Sat Feb 4 14:20:49 PST 2012
On 02/04/2012 11:04 PM, Era Scarecrow wrote:
>> Pure does not imply const in D. If you want stronger guarantees, just
>> turn 'test' into a const (or immutable) member function. In D, a
>> function can change anything that is mutable and reachable through its
>> parameters, this includes the implicit 'this' pointer. The reason for
>> this design is simple: There is no need to be overly restrictive,
>> because the additional restrictions are already trivially expressed in
>> the type system. Furthermore, any mutation of a parameter can be
>> turned into a less efficient protocol that only requires a const pure
>> function, so there would be no gain if pure implied const, it would
>> only make pure less useful.
>>
>> void foo(int* x)pure{*x+=2;}
>> int bar(const(int)*x)pure{return *x+2;}
>>
>> void main() pure{
>> int x, y;
>> foo(&x); // those two lines have
>> y = bar(&y); // equivalent functionality!
>> }
>
> Only external data I was implying, that was not based off the input
> arguments. Examples in the book refer that calculating Pi, or the square
> root of 2 is a constant and will always result in the same output,
> regardless the situation.
>
> Quote TDPL pg 165:
> "In D, a function is considered pure if returning a result is it's only
> effect and the result depends only on the function's arguments.
>
> Also, pure functions can run literally in parallel because they don't
> interact with the rest of the program except through their result."
Probably the restriction was lifted after TDPL was out.
>
> So... If we take a struct.
>
> struct X {
> int i;
> pure int squaredPlus(int x) {
> return x*x + i
> }
> alias squaredPlus sqp;
> }
>
> X st(15);
>
> writeln(st.sqp(0)); //15
> int i1 = st.sqp(10); st.i++;
> int i2 = st.sqp(10); st.i++;
> int i3 = st.sqp(10); st.i++;
> int i4 = st.sqp(10); st.i++;
>
> assert(i1 == 100); //pass/fail?
> assert(i2 == 101); //pass/fail?
> assert(i3 == 102); //pass/fail?
> assert(i4 == 103); //pass/fail?
> assert(s1.i == 104); //probably pass.
>
> If the compiler can reorder or run these in parallel (for optimization)
> or caches the result the first time (since it's suppose to always return
> the same value), what's correct in this case? This afterall isn't
> synchronized, even if it was, what's correct behavior? Am I wrong in
> understanding this?
Yes. The compiler will only reorder/run in parallel/optimize if it is
safe (not changing execution semantics). Pure can be used to prove that
certain optimizations are safe. If a pure function only takes const or
immutable arguments, the compiler has more guarantees and can do more
things. If a pure function takes mutable arguments, it can be used as a
component of other pure functions (important!), but the kind of
optimizations that can be performed directly on them are a lot more limited.
'Pure' means that the behavior of the function does not change between
invocations with the same/equivalent arguments. This can include
mutating actions on the arguments, if those are typed mutable.
More information about the Digitalmars-d-learn
mailing list