Pure functions in D

Bruno Medeiros brunodomedeiros+spam at com.gmail
Wed Sep 24 03:30:07 PDT 2008


Steven Schveighoffer wrote:
> "Bruno Medeiros" wrote
>> Steven Schveighoffer wrote:
>>> Another possibility is that pure functions that accept mutable parameters 
>>> can only be called from other pure functions, therefore you are 
>>> guaranteed that the data is not being used in any other thread.
>>>
>> I'm almost certain this is the intended behavior, with the addition that 
>> you can also call that same pure function from an unpure one, only then, 
>> the compiler will treat the function as being unpure. This is the gist of 
>> the "partially pure"/"contextually pure" idea: a function is considered 
>> pure or not dependent on the immutability of the arguments with which it's 
>> called. This consideration "happens" on every call. Since the 
>> optimizations to pure functions are made on the call, and not on the body 
>> of the function, this is perfectly ok.
>> I don't see any other behavior that isn't either broken, or more limited 
>> in functionality.
> 
> One of the benefits that Walter and Andrei's original purity plan provided 
> was that you could always assume that pure functions did not have to worry 
> about threading issues.  I think allowing a pure function that takes mutable 
> arguments to be callable from an unpure function removes that benefit.  I 
> hope this isn't the case.
> 
> Of course, if shared/unshared is implemented, and pure functions are only 
> allowed to be passed 'unshared' mutable data, then the benefit is still on.
> 
> I'm just unclear on what Walter is planning.  I admit I didn't read the 
> whole article, I just saw that quote and thought 'hm... that looks wrong'.
> 
>> Also note that in the case where the given (contextually) pure "foo" 
>> function is called from a pure function, the fact that foo is called from 
>> a pure function only guarantees that the arguments are not changed by 
>> anyone else when foo executes, but foo must still be treated as unpure. 
>> Example:
>>
>> pure void foo(int* iptr) {
>>   (*iptr)++; // side effect
>> }
>>
>>
>> pure int func() {
>>   int a = 1;
>>   foo(&a); // side-effect, cannot optimize this call
>>   foo(&a); // side-effect, cannot optimize this call
>>   return a;
>> }
>> // Yet func is allways pure.
> 
> I agree with you, partially pure functions can be called from pure functions 
> with limited optimization.  But if you allow foo to be called from an unpure 
> function you could have this problem:
> 
> int func2()
> {
>     static int a = 1;
>     foo(&a);
> }
> 
> Now, if 2 threads are calling func2, you have race conditions and threading 
> issues in foo, which seems to be a major concern that W/A were trying to 
> address.  And I hope they do address it, it was the one huge benefit I saw 
> from pure functions.
> 
> -Steve 
> 
> 

Yes, you can have race and threading issues in foo with that call. But 
what is the alternative? In the first pure system (in andrei's 
presentation) that call would not be allowed. So what you would do? 
You'd have to write another function just like foo (the same code), but 
that is not marked pure, and use that. But you'd still have the same 
synchronization problems.
If you don't want to have those issues, write a foo function that takes 
invariant parameters.
The partially pure functions (functions with mutable parameters), which 
basically have localized side-effects and are deterministic when called 
from "really-pure" functions, are not there to provide the full effects 
of really-pure functions. They are just a convenience for the writing 
the really-pure functions.

(Also, I'd reckon most static/global functions will be partially pure.)


-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D



More information about the Digitalmars-d mailing list