Partially pure (Re: Fully transitive const is not necessary)

Steven Schveighoffer schveiguy at yahoo.com
Thu Apr 3 08:55:58 PDT 2008


"Don Clugston" wrote
> Walter Bright wrote:
>> Bill Baxter wrote:
>>> So does that mean
>>>
>>>   pure int f(const Class c)
>>>   { ...
>>>   }
>>>
>>> will *not* be allowed?  Because some part of c *could* change, even if 
>>> it's not f() doing the changing.  I.e. another thread could be changing 
>>> c concurrently.
>>
>> Right. That declaration of f is erroneous.
>>
>>> If so, that seems unnecessarily restrictive to me.  Any side effect or 
>>> indeterminacy of f() in that case is not because of f()'s doing.  So 
>>> f()'s behavior *is* pure even if it takes a const argument.  It's not 
>>> f's fault if the environment it's living in is unstable.
>>
>> A function is pure or it isn't, there really isn't any room for 
>> "unstable" purity, or the point of purity is lost.
>
> I think there is. A function which accesses a global is inherently impure. 
> But, a function which takes a non-invariant argument, can in theory safely 
> be called from inside a pure function, provided any non-invariant 
> arguments are local variables, or invariant.
>
> eg.
>
> class C
> {
>   int numcalls;
>   this() { numcalls=0; }
>   void foo() { ++numcalls; } // Not pure - but no global side effects.
> }
>
> pure int bar(int x)
> {
>     C c = new C;
>     for (int i=0; i<x; ++i) c.foo();
>     return c.numcalls;
> }
>
> Is bar() pure or not?
>
> Incidentally this type of code currently works in CTFE.

Yes, bar is pure, but in order to be statically verifyable that it is pure, 
I think you need to slap a pure tag on C.foo, because without source code, 
the compiler cannot check foo to see if it accesses any other values.

I think Walter's vision is to have pure be statically verified by the 
compiler to ensure that one does not erroneously label a non-pure function 
as pure.  In this context, I am very interested to hear the set of rules 
that allow this.  What I am also interested is whether general pointers to 
non-invariant data will be allowed to be used.

For example:

char[] globaldata;

pure invariant(char)[] transform(invariant(char)[] input)
{
    char[] result = input.dup;
    // transform result
    return cast(invariant)result;
}

Will this compile?  If so, how does the compiler statically know during the 
transformation phase that result was pointing to data that was local, since 
it is on the heap?  Is the compiler going to 'tag' such variables as 
pure-safe?  i.e. how does it have the context information about result to 
know that it is ok to use, it could have been pointing to globaldata?

-Steve 





More information about the Digitalmars-d mailing list