Will compiler-enforced pure be too strict?

Craig Black craigblack2 at cox.net
Fri Apr 4 17:07:28 PDT 2008


"Don Clugston" <dac at nospam.com.au> wrote in message 
news:ft4lof$2e9v$1 at digitalmars.com...
> Craig Black wrote:
>> Don Clugston wrote:
>>> 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.
>>
>> The answer is yes bar is pure even though foo is not, because c is a 
>> local variable, so it's non-static fields won't be accessed by other 
>> threads. Unless I misunderstand, the rule is that a non-static 
>> class/struct variable that is local to a pure function can call a member 
>> function if that member function does not access global state.
>>
>> My question is, will the compiler be smart enough to know that bar is 
>> pure, even though foo is not?  Maybe we need some other keyword to denote 
>> that a function does not access any global/static variables.  Something 
>> like this:
>>
>> localstate void foo() { ++numcalls; }
>>
>> Or perhaps the compiler would be smart enough to know this without the 
>> keyword?
>
> I don't see how the compiler could do it, without access to the source 
> code.
> Also, if the compiler is doing this automatically, then if you add a 
> static variable inside foo(), you are changing the API of the function, 
> and bar() . Even though bar() as written is pure, it can't safely use 
> foo(), since foo() makes no guarantees that it won't become impure some 
> day.
>
> I can see a few options --
> * very strict pure, bar() above cannot be pure.
> * some way of signifying (new keyword?) that an arbitrary function has no 
> global state.
> * allow something like 'pure class'/'pure struct' for a class or struct 
> which is safe to use in circumstances like the above -- a class which 
> contains contains no statics, and which has no functions which access 
> local variables.
> * allow non-const member functions to be pure, even if they modify 'this'.
>
> Probably we'll initally get the first one, but hopefully we'll get 
> something like one of the other options eventually, otherwise pure 
> functions will be very limited.

I like the second option the best.  Maybe "local" keyword?

Sorry to change the subject, but even if we do get this, pure is not "The 
Solution" to concurrency.  One thing that is a little disappointing about 
pure is that it really doesn't help me with my concurrency issues.  I need 
to parallelize a time stamped ordered event queue, and I don't see how pure 
will help me.  I need something more advanced:  speculation heuristics about 
global state.  That is, a particular event can execute in parallel (out of 
order) if certain global state variables don't change.  There's a lot to 
this and like I said, pure doesn't help.

Features that would help me with concurrency are (1) static and non-static 
thread local storage, and (2) a way to prevent a function from accessing 
global variables (local keyword perhaps).  2 would not be useful for my 
purposes unless you can constrain a delegate to only accept "local" 
functions.

-Craig 




More information about the Digitalmars-d mailing list