should pure functions accept/deal with shared data?

Artur Skawina art.08.09 at gmail.com
Thu Jun 7 12:16:20 PDT 2012


On 06/07/12 20:29, Steven Schveighoffer wrote:
> On Thu, 07 Jun 2012 13:46:43 -0400, Artur Skawina <art.08.09 at gmail.com> wrote:
> 
>> On 06/07/12 18:45, Steven Schveighoffer wrote:
>>> On Thu, 07 Jun 2012 11:55:32 -0400, Artur Skawina <art.08.09 at gmail.com> wrote:
>>>
>>>> On 06/07/12 16:43, Steven Schveighoffer wrote:
>>>>> I understand the implementation is not correct for shared, and that actually is my point.  The current compiler lets you do the wrong thing without complaint.  Given that the shared version of the function needs to be written differently than the unshared version, we gain nothing but bugs by allowing pure functions that operate on shared.
>>>>>
>>>>> In essence, a pure-accepting-shared (PAS) function is not realistically useful from a strong-pure function.  A strong-pure function will have no ties to shared data, and while it may be able to create data that could potentially be shared, it can't actually share it!  So a PAS function being called from a strong-pure function is essentially doing extra work (even if it's not implemented, the expectation is it will be some day) for no reason.
>>>>>
>>>>> So since a PAS function cannot usefully be optimized (much better to write an unshared version, it's more accurate), and must be written separately from the unshared version, I see no good reason to allow shared in pure functions ever.  I think we gain a lot by not allowing it (more sanity for one thing!)
>>>>
>>>> While it's true that "shared" inside pure functions doesn't _look_ right, can you think
>>>> of a case where it is actually wrong, given the pure model currently in use?
>>>> Would inferring templated functions as impure if they access (and not just reference)
>>>> shared data help?
>>>
>>> I contend it would make marking a template as pure more useful -- you can with one keyword ban all use of shared via template parameters on a template function, given that it does not properly protect shared data from races.
>>
>> "not properly protecting shared data from races" is as language issue, it's not
>> specific to pure functions or templates. (Note: this does not mean that "shared"
>> currently does too little; it in fact does too much, but that's a completely
>> different issue)
>>
>> This
>>
>>    shared Atomic!int x;
>>
>>    void main() { x.inc(); };
>>
>> will do the right thing, even with your "void inc(T)(ref T i) pure" template.
> 
> Right, but if you want to handle shared too, just don't mark inc as pure.  There isn't any advantage to marking it pure.  The compiler will infer pure when it should.  Since pure functions (in the proposed fixed compiler) cannot handle shared data, there is no need to mark inc pure, it can always be called from a pure function.
> 
> Note that the above, while correct, is not a condition of shared.  That it *can* be made to work isn't a factor of inc.
> 
> But I can specify inc is pure, and if shared data isn't allowed, inc can be *sure* it's not going to be abused.  It's entirely possible to look at the inc function, and reason that it can't be used to make a race bug (assuming someone doesn't deliberately sabotage the increment operator on a type by casting away pure).
> 
>> Yes, it's not actually pure, but that won't be problem in practice because it
>> takes a mutable reference as input. You are proposing to disallow this.
> 
> I'm not proposing disallowing mutable references, just shared references.

I know, but if a D function marked as "pure" takes a mutable ref (which a shared
one has to be assumed to be), it won't be treated as really pure for optimization
purposes (yes, i'm deliberately trying to avoid "strong" and "weak"). And any caller
will have to obtain this shared ref either from a mutable argument or global state.
Hence that "pure" function with shared inputs will *never* actually be pure.
So I'm wondering what would be the gain from banning shared in weakly pure functions
(Ugh, you made me use that word after all ;) ).
AFAICT you're proposing to forbid something which currently is a NOOP. And the change
could have consequences for templated functions or lambdas, where "pure" is inferred. 

artur


More information about the Digitalmars-d mailing list