December 21, 2016
On 12/21/2016 03:10 PM, Johan Engelen wrote:
> On Wednesday, 21 December 2016 at 20:04:04 UTC, Johan Engelen wrote:
>>
>>   "Any `pure` function that is not strongly pure _may not be assumed
>> to be_ memoizable."
>
> That version of mine is also not correct :(
>
> How about: "A strongly pure function can be assumed to be memoizable.
> For a not strongly pure function, well, `pure` does not add information
> regarding memoizability."

OK save for the colloquial "well". -- Andrei


December 21, 2016
On 12/21/2016 03:59 PM, John Colvin wrote:
> On Wednesday, 21 December 2016 at 15:40:42 UTC, Andrei Alexandrescu wrote:
>> On 12/20/2016 05:49 PM, Andrei Alexandrescu wrote:
>>> https://github.com/dlang/dlang.org/pull/1528 -- Andrei
>>
>> Dropped the void functions. On to the next scandal:
>>
>>> A function that accepts only parameters without mutable indirections and
>>> returns a result that has mutable indirections is called a $(I pure
>>> factory
>>> function). An implementation may assume that all mutable memory
>>> returned by
>>> the call is not referenced by any other part of the program, i.e. it is
>>> newly allocated by the function.
>>
>>
>> Andrei
>
> There are 3 levels:
> 1) no idea what's going on: e.g. the function returns a mutable
> reference and also reads from global mutable memory.

That would be not pure.

> 2) memory must be new: e.g. returns 2 mutable references, no accessing
> external mutable memory.

Yah, they could refer one another.

> 3) memory must be new and uniquely referenced: function returns 1
> mutable reference, does not access external mutable memory.

Yah.

> If I'm not mistaken only 3 enables anything useful like implicit casts
> to immutable.

The formulation is careful to not specify what can be done. For now "not referenced by any other part of the program" nicely covers 2 and 3.

> Also, "returned references" should be extended to include "out"
> parameters, because there's no difference as far as memory uniqueness is
> concerned.

Cool idea.


Andrei
December 21, 2016
On Wednesday, 21 December 2016 at 21:34:04 UTC, Andrei Alexandrescu wrote:
> On 12/21/2016 03:04 PM, Johan Engelen wrote:
>> 
>> ```
>> I don't know what "required to honor all calls" means, but I guess it means
>> ```
>> auto a = foo(); // int* foo() pure;
>> auto b = foo();
>> ```
>> cannot be transformed to
>> ```
>> auto a = foo(); // int* foo() pure;
>> auto b = a;
>> ```
>
> That is correct.

Is that _all_ it is saying? Or is it also saying this:
```
void bar() {
   auto a = foo(); // int* foo() pure;
}

// cannot remove the call to bar, because bar calls a pure function and all calls must be "honored"
bar();
```

December 21, 2016
On Wednesday, 21 December 2016 at 21:34:04 UTC, Andrei Alexandrescu wrote:
> On 12/21/2016 03:04 PM, Johan Engelen wrote:
>
>> Super contrived, but I hope you get my drift:
>> ```
>> int *awesome() pure {
>>   static if (ohSoAwesome) {
>>      return new int;
>>   } else {
>>      return null;
>>   }
>> }
>> ```
>
> Where does ohSoAwesome come from?

A random bool.
Perhaps something like this:
```
version(LDC)
  ohSoAwesome = true;
else
  ohSoAwesome = false
```

;-)
  Johan

December 21, 2016
On 12/21/2016 04:42 PM, Johan Engelen wrote:
> On Wednesday, 21 December 2016 at 21:34:04 UTC, Andrei Alexandrescu wrote:
>> On 12/21/2016 03:04 PM, Johan Engelen wrote:
>>
>>> Super contrived, but I hope you get my drift:
>>> ```
>>> int *awesome() pure {
>>>   static if (ohSoAwesome) {
>>>      return new int;
>>>   } else {
>>>      return null;
>>>   }
>>> }
>>> ```
>>
>> Where does ohSoAwesome come from?
>
> A random bool.
> Perhaps something like this:
> ```
> version(LDC)
>   ohSoAwesome = true;
> else
>   ohSoAwesome = false
> ```

Well randomness is not available in pure functions. Anyhow I've reformulated the wording and added an example. The sheer fact it works is pretty awesome.

https://github.com/dlang/dlang.org/pull/1528

For now I didn't want to give thrown values any special treatment, i.e. maximum freedom for the implementation.


Andrei

December 22, 2016
On Wednesday, 21 December 2016 at 22:08:58 UTC, Andrei Alexandrescu wrote:
>
> Well randomness is not available in pure functions.

Internet discussions... a misunderstanding, I should've been more careful.
I meant "an arbitrary boolean value", not something random (e.g. the version(LDC) thing).

> Anyhow I've reformulated the wording and added an example. The sheer fact it works is pretty awesome.
>
> https://github.com/dlang/dlang.org/pull/1528

Perhaps you forgot to push, I see no update.
December 22, 2016
On 12/22/2016 11:45 AM, Johan Engelen wrote:
> On Wednesday, 21 December 2016 at 22:08:58 UTC, Andrei Alexandrescu wrote:
>>
>> Well randomness is not available in pure functions.
>
> Internet discussions... a misunderstanding, I should've been more careful.
> I meant "an arbitrary boolean value", not something random (e.g. the
> version(LDC) thing).
>
>> Anyhow I've reformulated the wording and added an example. The sheer
>> fact it works is pretty awesome.
>>
>> https://github.com/dlang/dlang.org/pull/1528
>
> Perhaps you forgot to push, I see no update.

Thanks! Pushed just now. -- Andrei
December 22, 2016
On Wednesday, 21 December 2016 at 01:05:50 UTC, Jonathan M Davis wrote:
> On Tuesday, December 20, 2016 19:58:38 Andrei Alexandrescu via Digitalmars-d wrote:
>> On 12/20/16 7:40 PM, Timon Gehr wrote:
>> > On 20.12.2016 23:49, Andrei Alexandrescu wrote:
>> >> https://github.com/dlang/dlang.org/pull/1528 -- Andrei
>> >
>> > Good, except:
>> >
>> > "$(P `pure` functions returning `void` will be always called even if it is strongly `pure`. The implementation must assume the function does something outside the confines of the type system and is therefore not allowed to elide the call, even if it appears to have no possible effect.)"
>> >
>> > I think this makes no sense. What is the idea behind this paragraph?
>>
>> A function that traces execution via a debug statement, for example. -- Andrei
>
> Well, ultimately, strongly pure functions that return void are either doing something that works around the type system (e.g. using debug statements to do operations which aren't pure), or they arguably shouldn't even compile, because they can't possibly do anything that has any effect on the program beyond eating up CPU time. So, as far as I can tell, we should either make an exception for them (as the PR currently does) or make them illegal.

It seems to me that a pure function could have a variety of
acceptable side effects which don't modify active memory and
that don't work around the type system or necessarily eat
significant CPU time, and that you probably don't want to
have elided.  Here are some examples.

(1) Serve as a convenient breakpoint handle in the debugger, perhaps
    as a kind of centralized this_cannot_ever_happen() function.
(2) conditionally_die(conditions);
(3) Sleep for some run-time-computable length of time.
(4) Yield the thread so other threads can take execution priority.
(5) Yield the entire process so other processes can take execution
    priority.
(6) Wait for an external trigger (perhaps a hardware interrupt, for
    instance).
(7) Invoke a pass of garbage collection.

Aside from the first, whether or not the pure function actually takes
that action might depend on some complex calculation run inside the
pure function.

My point here is that when considering what functions do, mutating
memory is only part of the story.  Control of time and other resources
can be a critical part of overall program execution, and you don't want
the compiler assuming it can ignore such aspects.
December 22, 2016
On Thursday, 22 December 2016 at 18:04:51 UTC, Observer wrote:

> (1) Serve as a convenient breakpoint handle in the debugger, perhaps
>     as a kind of centralized this_cannot_ever_happen() function.
> (2) conditionally_die(conditions);
> (3) Sleep for some run-time-computable length of time.
> (4) Yield the thread so other threads can take execution priority.
> (5) Yield the entire process so other processes can take execution
>     priority.
> (6) Wait for an external trigger (perhaps a hardware interrupt, for
>     instance).
> (7) Invoke a pass of garbage collection.


A function that does any of that cannot be pure.
December 22, 2016
On Wednesday, 21 December 2016 at 21:34:04 UTC, Andrei Alexandrescu wrote:
>> Instead of
>>   "Any `pure` function that is not strongly pure cannot be memoized."
>> why not
>>   "Any `pure` function that is not strongly pure _may not be assumed to
>> be_ memoizable."
>
> Got it. Good point. Will do.
>

That worse than the current wording.

Strongly pure function can be memoized doesn't mean that non strongly pure function can never be, just that the compiler would have to prove it is correct to do so before doing it.

On the other hand, this new wording do not guarantee that the compiler can do memorization on strongly pure functions. I don't think this is reasonable and in effect, makes pure useless for the optimizer outside of trivial cases. If you lie to the compiler by bypassing the type system in the pure function, that's on you. All user should not be penalized because someone decided they were very smart and got hoisted by their own petard.