September 22, 2010
Robert Jacques wrote:
> On Wed, 22 Sep 2010 07:54:26 -0400, Michel Fortin <michel.fortin@michelf.com> wrote:
> 
>> On 2010-09-22 01:26:01 -0400, "Robert Jacques" <sandford@jhu.edu> said:
>>
>>> So removing the concurrency safety from pure would greatly  expand the number of pure functions, however, automatic parallelism would  be lost.
>>
>> Don clearly mentioned that this is not lost. Basically, for safe parallelism what you need is a function that has a) pure and b) no mutable reference parameter. Both are easily checkable at compile time, you'd just need to change your test for pure for a test that also checks the arguments.
> 
> What is lost is my ability to declare a function does x in the signature and for the compiler to check that. I really want to know if code monkey A changed some type's implementation to be thread unsafe, because detecting and tracking down a loss of performance due to loss of automatic parallelism is devilish.

No, you haven't lost that at all. Any function marked as pure still has no access to any state, other than what is provided by its parameters. It is still thread-safe.

>> The interesting thing with this change is that you can now call mutators functions on the local variables inside the pure function, because those can be made pure. You can't even iterate over a range inside a pure function without this!
>>
>>     pure int test() {
>>         int result;
>>         auto r = iota(0, 10);
>>         while (!r.empty) {
>>             result += r;
>>             r.popFront(); // can't be pure by current rules!
>>         }
>>         return result;
>>     }
>>
> 
> I did mention this benefit in my post, but this example really shows just how awesome it really is. Which is why I think the concept of a simplified pure is so powerful and be included in the language. I just want it included in addition to the current pure concept.

The current pure concept is still included. The syntax for strong pure is simply a function declaration with no mutable parameters.
So all existing functions marked 'pure' would remain strong pure.


The one situation where things get more complicated is if you have a templated function marked as pure, and you want to ensure that it is strong pure.
An isStrongPure!(T) template would need to be written, and used in the template constraint.
September 22, 2010
Robert Jacques wrote:
> On Wed, 22 Sep 2010 04:13:34 -0400, Don <nospam@nospam.com> wrote:
> 
>> Don wrote:
>>> The docs currently state that:
>>
>>> PROPOSAL:
>>> Drop the first requirement. Only one requirement is necessary:
>>>  A pure function does not read or write any global mutable state.
>>>
>>
>> Wow. It seems that not one person who has responded so far has understood this proposal! I'll try again. Under this proposal:
> 
> Funny, your re-iteration appears to coincided to my previous understanding. So either I've mis-understood twice, or I didn't sufficiently demonstrate my understanding when I made my critique. :) That said, I do think this version is much clearer and understandable.
> 
>> If you see a function which has mutable parameters, but is marked as 'pure', you can only conclude that it doesn't use global variables. That's not much use on it's own. Let's call this a 'weakly-pure' function.
>>
>> However, if you see a function maked as 'pure', which also has only immutable parameters, you have the same guarantee which 'pure' gives us as the moment. Let's call this a 'strongly-pure' function.
>>
>> The benefit of the relaxed rule is that a strongly-pure function can call a weakly-pure functions, while remaining strongly-pure.
>> This allows very many more functions to become strongly pure.
>>
>> The point of the proposal is *not* to provide the weak guarantee. It is to provide the strong guarantee in more situations.
> 
> The problem from my point of view is that the programmer can not declare that a function should be 'strongly-pure' or 'weakly-pure'.

Yes they can. They just need to declare the parameters to be immutable.

 Essentially,
> the point of the proposal is *to* provide the weak guarantee and leave the strong guarantee up to a sufficiently smart compiler. 

No it is not.
The key point you're not getting is that the difference between strong and weak purity can be determined from the function signature alone. You can do it in a very simple piece of library code.
The compiler doesn't need to be involved at all. It's utterly trivial.

Establishing weak purity, OTOH, is very complicated, and requires the compiler _and the linker_.

And I really
> don't want a function to suddenly run 8x slower, just because Joe-coder changed a type somewhere and made my 'strongly-pure' inner-loop 'weakly-pure'. That said, if we can only have one type of purity in the language, I think 'weakly-pure' is more powerful a concept than 'strongly-pure'.
September 22, 2010
On Wed, 22 Sep 2010 11:44:00 -0400, Don <nospam@nospam.com> wrote:

> Robert Jacques wrote:
>> On Wed, 22 Sep 2010 07:54:26 -0400, Michel Fortin <michel.fortin@michelf.com> wrote:
>>
>>> On 2010-09-22 01:26:01 -0400, "Robert Jacques" <sandford@jhu.edu> said:
>>>
>>>> So removing the concurrency safety from pure would greatly  expand the number of pure functions, however, automatic parallelism would  be lost.
>>>
>>> Don clearly mentioned that this is not lost. Basically, for safe parallelism what you need is a function that has a) pure and b) no mutable reference parameter. Both are easily checkable at compile time, you'd just need to change your test for pure for a test that also checks the arguments.
>>  What is lost is my ability to declare a function does x in the signature and for the compiler to check that. I really want to know if code monkey A changed some type's implementation to be thread unsafe, because detecting and tracking down a loss of performance due to loss of automatic parallelism is devilish.
>
> No, you haven't lost that at all. Any function marked as pure still has no access to any state, other than what is provided by its parameters. It is still thread-safe.

No, it isn't. A strongly-pure function is thread safe, but a weakly-pure function isn't. Since strong/weak is automatically determined by the compiler, a function's strength can switch due to long distance code changes. This wouldn't be an issue today, but tomorrow large strongly-pure functions will be parallelized automatically in a manner akin to inlining (outlining?). Then it makes a difference. However, these issues feel more like D3 concerns than D2 concerns, particularly when you consider the advantages of making tasks/futures a language level concept.
September 22, 2010
On Wed, 22 Sep 2010 11:53:22 -0400, Don <nospam@nospam.com> wrote:

> Robert Jacques wrote:
>> On Wed, 22 Sep 2010 04:13:34 -0400, Don <nospam@nospam.com> wrote:
>>
>>> Don wrote:
>>>> The docs currently state that:
>>>
>>>> PROPOSAL:
>>>> Drop the first requirement. Only one requirement is necessary:
>>>>  A pure function does not read or write any global mutable state.
>>>>
>>>
>>> Wow. It seems that not one person who has responded so far has understood this proposal! I'll try again. Under this proposal:
>>  Funny, your re-iteration appears to coincided to my previous understanding. So either I've mis-understood twice, or I didn't sufficiently demonstrate my understanding when I made my critique. :) That said, I do think this version is much clearer and understandable.
>>
>>> If you see a function which has mutable parameters, but is marked as 'pure', you can only conclude that it doesn't use global variables. That's not much use on it's own. Let's call this a 'weakly-pure' function.
>>>
>>> However, if you see a function maked as 'pure', which also has only immutable parameters, you have the same guarantee which 'pure' gives us as the moment. Let's call this a 'strongly-pure' function.
>>>
>>> The benefit of the relaxed rule is that a strongly-pure function can call a weakly-pure functions, while remaining strongly-pure.
>>> This allows very many more functions to become strongly pure.
>>>
>>> The point of the proposal is *not* to provide the weak guarantee. It is to provide the strong guarantee in more situations.
>>  The problem from my point of view is that the programmer can not declare that a function should be 'strongly-pure' or 'weakly-pure'.
>
> Yes they can. They just need to declare the parameters to be immutable.

What about value types?
September 22, 2010
On Wed, 22 Sep 2010 11:55:57 -0400, Robert Jacques <sandford@jhu.edu> wrote:

> On Wed, 22 Sep 2010 11:44:00 -0400, Don <nospam@nospam.com> wrote:
>
>> Robert Jacques wrote:
>>> On Wed, 22 Sep 2010 07:54:26 -0400, Michel Fortin <michel.fortin@michelf.com> wrote:
>>>
>>>> On 2010-09-22 01:26:01 -0400, "Robert Jacques" <sandford@jhu.edu> said:
>>>>
>>>>> So removing the concurrency safety from pure would greatly  expand the number of pure functions, however, automatic parallelism would  be lost.
>>>>
>>>> Don clearly mentioned that this is not lost. Basically, for safe parallelism what you need is a function that has a) pure and b) no mutable reference parameter. Both are easily checkable at compile time, you'd just need to change your test for pure for a test that also checks the arguments.
>>>  What is lost is my ability to declare a function does x in the signature and for the compiler to check that. I really want to know if code monkey A changed some type's implementation to be thread unsafe, because detecting and tracking down a loss of performance due to loss of automatic parallelism is devilish.
>>
>> No, you haven't lost that at all. Any function marked as pure still has no access to any state, other than what is provided by its parameters. It is still thread-safe.
>
> No, it isn't. A strongly-pure function is thread safe, but a weakly-pure function isn't. Since strong/weak is automatically determined by the compiler, a function's strength can switch due to long distance code changes. This wouldn't be an issue today, but tomorrow large strongly-pure functions will be parallelized automatically in a manner akin to inlining (outlining?). Then it makes a difference. However, these issues feel more like D3 concerns than D2 concerns, particularly when you consider the advantages of making tasks/futures a language level concept.

It's thread safe.  Calling a strongly-pure function concurrently on two threads is not multi-threading, it's an optimization.
September 22, 2010
On Wed, 22 Sep 2010 12:00:16 -0400, Robert Jacques <sandford@jhu.edu> wrote:

> On Wed, 22 Sep 2010 11:53:22 -0400, Don <nospam@nospam.com> wrote:
>
>> Robert Jacques wrote:
>>> On Wed, 22 Sep 2010 04:13:34 -0400, Don <nospam@nospam.com> wrote:
>>>
>>>> Don wrote:
>>>>> The docs currently state that:
>>>>
>>>>> PROPOSAL:
>>>>> Drop the first requirement. Only one requirement is necessary:
>>>>>  A pure function does not read or write any global mutable state.
>>>>>
>>>>
>>>> Wow. It seems that not one person who has responded so far has understood this proposal! I'll try again. Under this proposal:
>>>  Funny, your re-iteration appears to coincided to my previous understanding. So either I've mis-understood twice, or I didn't sufficiently demonstrate my understanding when I made my critique. :) That said, I do think this version is much clearer and understandable.
>>>
>>>> If you see a function which has mutable parameters, but is marked as 'pure', you can only conclude that it doesn't use global variables. That's not much use on it's own. Let's call this a 'weakly-pure' function.
>>>>
>>>> However, if you see a function maked as 'pure', which also has only immutable parameters, you have the same guarantee which 'pure' gives us as the moment. Let's call this a 'strongly-pure' function.
>>>>
>>>> The benefit of the relaxed rule is that a strongly-pure function can call a weakly-pure functions, while remaining strongly-pure.
>>>> This allows very many more functions to become strongly pure.
>>>>
>>>> The point of the proposal is *not* to provide the weak guarantee. It is to provide the strong guarantee in more situations.
>>>  The problem from my point of view is that the programmer can not declare that a function should be 'strongly-pure' or 'weakly-pure'.
>>
>> Yes they can. They just need to declare the parameters to be immutable.
>
> What about value types?

Value types are implicitly convertable to immutable, so they can be strongly-pure.  The problem I think Robert is referring to is, a person cannot always tell just from looking at a signature that a type is strongly-pure qualified or not.

For example, is this function weak or strong?

pure int foo(T t);

But the compiler will be able to tell.  I think adding a __traits(isStronglyPure, symbol) will be good for those rare occasions where you really want to ensure purity.

static assert(__traits(isStronglyPure, foo));

-Steve
September 22, 2010
On 9/22/10 7:10 PM, Steven Schveighoffer wrote:
> But the compiler will be able to tell. I think adding a
> __traits(isStronglyPure, symbol) will be good for those rare occasions
> where you really want to ensure purity.
>
> static assert(__traits(isStronglyPure, foo));
>
> -Steve

Shouldn't it be possible to implement that in a library template, not requiring any additions to the compiler at all?
September 22, 2010
On Wed, 22 Sep 2010 14:03:05 -0400, klickverbot <see@klickverbot.at> wrote:

> On 9/22/10 7:10 PM, Steven Schveighoffer wrote:
>> But the compiler will be able to tell. I think adding a
>> __traits(isStronglyPure, symbol) will be good for those rare occasions
>> where you really want to ensure purity.
>>
>> static assert(__traits(isStronglyPure, foo));
>>
>> -Steve
>
> Shouldn't it be possible to implement that in a library template, not requiring any additions to the compiler at all?

Well, if you can convert foo to it's parameter types, maybe.  But the compiler will already be doing this, won't it?  If it's not, then what's the point of caring?

-Steve
September 22, 2010
klickverbot wrote:
> On 9/22/10 7:10 PM, Steven Schveighoffer wrote:
>> But the compiler will be able to tell. I think adding a
>> __traits(isStronglyPure, symbol) will be good for those rare occasions
>> where you really want to ensure purity.
>>
>> static assert(__traits(isStronglyPure, foo));
>>
>> -Steve
> 
> Shouldn't it be possible to implement that in a library template, not requiring any additions to the compiler at all?

Yes. In fact, it's easy.
September 22, 2010
Robert Jacques wrote:
> On Wed, 22 Sep 2010 11:44:00 -0400, Don <nospam@nospam.com> wrote:
> 
>> Robert Jacques wrote:
>>> On Wed, 22 Sep 2010 07:54:26 -0400, Michel Fortin <michel.fortin@michelf.com> wrote:
>>>
>>>> On 2010-09-22 01:26:01 -0400, "Robert Jacques" <sandford@jhu.edu> said:
>>>>
>>>>> So removing the concurrency safety from pure would greatly  expand the number of pure functions, however, automatic parallelism would  be lost.
>>>>
>>>> Don clearly mentioned that this is not lost. Basically, for safe parallelism what you need is a function that has a) pure and b) no mutable reference parameter. Both are easily checkable at compile time, you'd just need to change your test for pure for a test that also checks the arguments.
>>>  What is lost is my ability to declare a function does x in the signature and for the compiler to check that. I really want to know if code monkey A changed some type's implementation to be thread unsafe, because detecting and tracking down a loss of performance due to loss of automatic parallelism is devilish.
>>
>> No, you haven't lost that at all. Any function marked as pure still has no access to any state, other than what is provided by its parameters. It is still thread-safe.
> 
> No, it isn't. A strongly-pure function is thread safe, but a weakly-pure function isn't. Since strong/weak is automatically determined by the compiler, a function's strength can switch due to long distance code changes. 

This is completely incorrect. It can only change strength if its signature changes.

This wouldn't be an issue today, but tomorrow large
> strongly-pure functions will be parallelized automatically in a manner akin to inlining (outlining?). Then it makes a difference. However, these issues feel more like D3 concerns than D2 concerns, particularly when you consider the advantages of making tasks/futures a language level concept.