June 19, 2012
On 06/19/2012 12:49 PM, Iain Buclaw wrote:
> On 19 June 2012 10:47, Christophe Travert<travert@phare.normalesup.org>  wrote:
>> Iain Buclaw , dans le message (digitalmars.D:170145), a écrit :
>>> On 19 June 2012 09:18, Don Clugston<dac@nospam.com>  wrote:
>>>> So would I. Can you think of one?
>>>> It was the best name I could come up with, given that the 'pure' was the
>>>> keyword.
>>>> We want a word that means 'no hidden state'.
>>>
>>> I thought that was what pure was for. :~)
>>>
>>> --
>>> Iain Buclaw
>>>
>>> *(p<  e ? p++ : p) = (c&  0x0f) + '0';
>>
>>
>> A delegate does have a frame pointer, and it's not that well hidden. If
>> you want no such 'hidden state', you do not want a delegate, you want a
>> function pointer. That means all delegates are weakly pure (until they
>> have an immutable frame pointer qualifier).
>>
>> If you want that this 'hidden state' does not change, that is another
>> story. pure for a delegate could mean that the frame pointer does not
>> change, but then, pure methods wouldn't allow you to make pure
>> delegates:
>>
>> struct S
>> {
>>   int i;
>>   int foo() pure { return i; }
>> }
>>
>> S s;
>> int delegate() pure dg =&s.foo;
>> // error if pure change meaning when applied to a delegate
>>
>
> So we have a few combinations then:
>
> pure  - as in weakly pure, guarantees not to change global state, but
> may alter it's own hidden state.
>
> pure nothrow - as in strongly pure, where is guaranteed not to have
> any side effects, so is suitable for constant folding

This would need to be qualified 'pure immutable nothrow', otherwise it
might change it's own hidden state.

> / the usual optimisations for a function typically marked as __pure__ in C.
>

Some of them can even be applied if it is just 'pure immutable '. loop
invariant code motion, for instance.

> pure const - similar to strongly pure, as is guaranteed not to be able
> to alter its own state (as it's const), but still may have side
> effects / throw an exception.
>

Therefore, you think 'pure const' should be allowed to have side effects?

>
> Make much sense? :-)
>

June 19, 2012
On 19 June 2012 12:03, deadalnix <deadalnix@gmail.com> wrote:
> Le 19/06/2012 12:49, Iain Buclaw a écrit :
>
>> So we have a few combinations then:
>>
>> pure  - as in weakly pure, guarantees not to change global state, but may alter it's own hidden state.
>>
>> pure nothrow - as in strongly pure, where is guaranteed not to have any side effects, so is suitable for constant folding / the usual optimisations for a function typically marked as __pure__ in C.
>>
>> pure const - similar to strongly pure, as is guaranteed not to be able to alter its own state (as it's const), but still may have side effects / throw an exception.
>>
>>
>> Make much sense? :-)
>>
>
> You know that it doesn't make any sense, right ?

ramble, ramble, ramble, ramble. :o)

-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
June 19, 2012
On 19 June 2012 12:04, Timon Gehr <timon.gehr@gmx.ch> wrote:
> On 06/19/2012 12:49 PM, Iain Buclaw wrote:
>>
>> On 19 June 2012 10:47, Christophe Travert<travert@phare.normalesup.org>  wrote:
>>>
>>> Iain Buclaw , dans le message (digitalmars.D:170145), a écrit :
>>>>
>>>> On 19 June 2012 09:18, Don Clugston<dac@nospam.com>  wrote:
>>>>>
>>>>> So would I. Can you think of one?
>>>>> It was the best name I could come up with, given that the 'pure' was
>>>>> the
>>>>> keyword.
>>>>> We want a word that means 'no hidden state'.
>>>>
>>>>
>>>> I thought that was what pure was for. :~)
>>>>
>>>> --
>>>> Iain Buclaw
>>>>
>>>> *(p<  e ? p++ : p) = (c&  0x0f) + '0';
>>>
>>>
>>>
>>> A delegate does have a frame pointer, and it's not that well hidden. If you want no such 'hidden state', you do not want a delegate, you want a function pointer. That means all delegates are weakly pure (until they have an immutable frame pointer qualifier).
>>>
>>> If you want that this 'hidden state' does not change, that is another story. pure for a delegate could mean that the frame pointer does not change, but then, pure methods wouldn't allow you to make pure delegates:
>>>
>>> struct S
>>> {
>>>  int i;
>>>  int foo() pure { return i; }
>>> }
>>>
>>> S s;
>>> int delegate() pure dg =&s.foo;
>>> // error if pure change meaning when applied to a delegate
>>>
>>
>> So we have a few combinations then:
>>
>> pure  - as in weakly pure, guarantees not to change global state, but may alter it's own hidden state.
>>
>> pure nothrow - as in strongly pure, where is guaranteed not to have any side effects, so is suitable for constant folding
>
>
> This would need to be qualified 'pure immutable nothrow', otherwise it might change it's own hidden state.
>
>
>> / the usual optimisations for a function typically marked as __pure__ in C.
>>
>
> Some of them can even be applied if it is just 'pure immutable '. loop invariant code motion, for instance.
>
>
>> pure const - similar to strongly pure, as is guaranteed not to be able to alter its own state (as it's const), but still may have side effects / throw an exception.
>>
>
> Therefore, you think 'pure const' should be allowed to have side effects?
>

Throwing exceptions is a bit of a side effect...


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
June 19, 2012
On 06/19/2012 01:24 PM, Iain Buclaw wrote:
> On 19 June 2012 12:04, Timon Gehr<timon.gehr@gmx.ch>  wrote:
>> On 06/19/2012 12:49 PM, Iain Buclaw wrote:
>>>  ...
>>> pure const - similar to strongly pure, as is guaranteed not to be able
>>> to alter its own state (as it's const), but still may have side
>>> effects / throw an exception.
>>>
>>
>> Therefore, you think 'pure const' should be allowed to have side effects?
>>
>
> Throwing exceptions is a bit of a side effect...
>

It is not. Any pure function can be turned into a pure nothrow function
by making the thrown exception an 'out' parameter and updating all
callers accordingly.



June 19, 2012
On 06/19/2012 01:29 PM, Timon Gehr wrote:
> On 06/19/2012 01:24 PM, Iain Buclaw wrote:
>> On 19 June 2012 12:04, Timon Gehr<timon.gehr@gmx.ch> wrote:
>>> On 06/19/2012 12:49 PM, Iain Buclaw wrote:
>>>> ...
>>>> pure const - similar to strongly pure, as is guaranteed not to be able
>>>> to alter its own state (as it's const), but still may have side
>>>> effects / throw an exception.
>>>>
>>>
>>> Therefore, you think 'pure const' should be allowed to have side
>>> effects?
>>>
>>
>> Throwing exceptions is a bit of a side effect...
>>
>
> It is not. Any pure function can be turned into a pure nothrow function
> by making the thrown exception an 'out' parameter and updating all
> callers accordingly.
>

Except 'main'. So throwing exceptions is a bit of a side effect after all.
June 19, 2012
On 06/19/12 09:59, deadalnix wrote:
> Le 19/06/2012 00:16, Artur Skawina a écrit :
>> On 06/18/12 23:08, deadalnix wrote:
>>> Le 18/06/2012 09:14, Mehrdad a écrit :
>>>> Okay, how about this? http://ideone.com/VMlzS
>>>>
>>>> Does this break const?
>>>>
>>>>
>>>> import std.stdio;
>>>> class S
>>>> {
>>>> this(int a)
>>>> {
>>>> this.a = a;
>>>> this.increment = { this.a++; };
>>>> }
>>>> int a;
>>>> void delegate() increment;
>>>> void oops() const { this.increment(); }
>>>> }
>>>> void main()
>>>> {
>>>> auto c = new const(S)(0);
>>>> writeln(c.a);
>>>> c.oops();
>>>> writeln(c.a);
>>>> }
>>>
>>> Depending on how it is specified, I think you should either :
>>>   - get an error when constructing c, because S isn't « constable ». (delegate type cannot be consted, but can be unconsted safely).
>>>   - get an error when you try to call increment in oops, because the delegate type can't ensure the constness of the operation.
>>>
>>
>> I'm afraid that:
>>
>> - Banning implicit mutable->const conversions would do far more harm,
>>    so this would not be a good solution to the problem.
>> - Requiring that the type of the delegate "ensure the constness" would
>>    be far too restrictive. (the question would be: "Is any data reachable
>>    via 'this' also reachable through the delegates context pointer?" and
>>    every such delegate would of course need to be "pure" [1].
>>
>> [This isn't *just* about the above example, you get the same problems
>>   when a const object isn't created but received from somewhere.]
>>
>> artur
>>
>> [1] which is a misnomer.
> 
> Due to D concept of weak purity, this doesn't ensure the required what we need here.

Actually, it does - if it can be proved that the delegate can't alter the object via the context pointer (eg because whatever it points to is not mutable) then even D's "pure" is enough. Because the delegate would need to be passed a mutable ref to be able to alter the object, which then could hardly be constructed as "breaking" constness.

But such a limit (const/immutable context) would be a problem for the cases where the delegate needs to alter some state (like export the result of some operation), but does _not_ modify the object it's embedded in. Note that the current object may very well be reachable (and mutable) from the delegate - but at some point you have to trust the programmer. Sure, fixing this hole would be great, but /how/ - w/o incurring unacceptable collateral damage?

> It is possible to get the error when trying to call the delegate instead of preventing to make it const, as I said in the post you quote. It is probably a better solution.

Any delegate?


On 06/19/12 10:18, Don Clugston wrote:
> On 18/06/12 17:00, Artur Skawina wrote:
>> D's "weak pure" can help; I just don't like the redefinition of the term "purity"; another name for "weak purity" would be better.
> 
> So would I. Can you think of one?
> It was the best name I could come up with, given that the 'pure' was the keyword.
> We want a word that means 'no hidden state'.

No, I can't think of an appropriate term either, from the current keyword list. Plus, inventing yet another one just leads to function qualifier hell. But, as it is, you're not able to mark a function as ("stronly") pure if it takes const args w/o resorting to pragmas. Immutable data is not always the solution. And having almost everything marked as "pure", when all it does is it prevents global/static accesses and does not influence codegen in any way, only creates confusion.

artur
June 19, 2012
On 06/19/2012 10:18 AM, Don Clugston wrote:
> On 18/06/12 17:00, Artur Skawina wrote:
>> ...
>>
>> D's "weak pure" can help; I just don't like the redefinition of the term
>> "purity"; another name for "weak purity" would be better.
>
> So would I. Can you think of one?
> It was the best name I could come up with, given that the 'pure' was the
> keyword.
> We want a word that means 'no hidden state'.

nostatic
stateless
monadic
June 19, 2012
Le 19/06/2012 14:30, Artur Skawina a écrit :
>> Due to D concept of weak purity, this doesn't ensure the required what we need here.
>
> Actually, it does - if it can be proved that the delegate can't alter the object
> via the context pointer (eg because whatever it points to is not mutable) then
> even D's "pure" is enough. Because the delegate would need to be passed a mutable
> ref to be able to alter the object, which then could hardly be constructed as
> "breaking" constness.
>
> But such a limit (const/immutable context) would be a problem for the cases where
> the delegate needs to alter some state (like export the result of some operation),
> but does _not_ modify the object it's embedded in. Note that the current object may
> very well be reachable (and mutable) from the delegate - but at some point you have
> to trust the programmer. Sure, fixing this hole would be great, but /how/ - w/o
> incurring unacceptable collateral damage?
>

This isn't a problem as long as the delegate isn't a member of the object. If it is, transitivity is broken, which is something you don't want.

Relying on the trust on the programmer is a dumb idea. Human do mistake, way more than computers. The basic behavior MUST be a safe one.

Transitivity has been introduced for good reason and language already provide a way to break it via cast. So it is unacceptable to rely on programmer on that point.

>> It is possible to get the error when trying to call the delegate instead of preventing to make it const, as I said in the post you quote. It is probably a better solution.
>
> Any delegate?
>

No, any delegate that have type that isn't covariant with the expected delegate type.
June 19, 2012
On 06/19/12 15:29, deadalnix wrote:
> Le 19/06/2012 14:30, Artur Skawina a écrit :
>>> Due to D concept of weak purity, this doesn't ensure the required what we need here.
>>
>> Actually, it does - if it can be proved that the delegate can't alter the object via the context pointer (eg because whatever it points to is not mutable) then even D's "pure" is enough. Because the delegate would need to be passed a mutable ref to be able to alter the object, which then could hardly be constructed as "breaking" constness.
>>
>> But such a limit (const/immutable context) would be a problem for the cases where the delegate needs to alter some state (like export the result of some operation), but does _not_ modify the object it's embedded in. Note that the current object may very well be reachable (and mutable) from the delegate - but at some point you have to trust the programmer. Sure, fixing this hole would be great, but /how/ - w/o incurring unacceptable collateral damage?
>>
> 
> This isn't a problem as long as the delegate isn't a member of the object. If it is, transitivity is broken, which is something you don't want.
> 
> Relying on the trust on the programmer is a dumb idea. Human do mistake, way more than computers. The basic behavior MUST be a safe one.
> 
> Transitivity has been introduced for good reason and language already provide a way to break it via cast. So it is unacceptable to rely on programmer on that point.
> 
>>> It is possible to get the error when trying to call the delegate instead of preventing to make it const, as I said in the post you quote. It is probably a better solution.
>>
>> Any delegate?
>>
> 
> No, any delegate that have type that isn't covariant with the expected delegate type.

   struct S {
      int i; this(int i) { this.i = i; }
      T* p;
      void f(int i) { this.i = i; /*p.i++;*/ }
   }
   struct T {
      int i; this(int i) { this.i = i; }
      void delegate(int i) f;
   }

   void main() {
      auto t = new T(42);
      auto s = new S(17);
      s.p = t;
      t.f = &s.f;
      f(t);
   }

   void f(const (T)* t) {
      t.f(t.i*2);
   }

You're proposing to make the last 'f' function illegal, just because the
commented out part could happen. I'm saying that this is unlikely to happen
*by accident*, and of course would still be possible by casting away the
constness.
But banning "unsafe" delegates would result in casts *when using "safe" ones*
- which is not a real improvement because this would make the "bad" casts much
harder to spot.

artur
June 19, 2012
Le 19/06/2012 16:16, Artur Skawina a écrit :
> On 06/19/12 15:29, deadalnix wrote:
>> Le 19/06/2012 14:30, Artur Skawina a écrit :
>>>> Due to D concept of weak purity, this doesn't ensure the required what we need here.
>>>
>>> Actually, it does - if it can be proved that the delegate can't alter the object
>>> via the context pointer (eg because whatever it points to is not mutable) then
>>> even D's "pure" is enough. Because the delegate would need to be passed a mutable
>>> ref to be able to alter the object, which then could hardly be constructed as
>>> "breaking" constness.
>>>
>>> But such a limit (const/immutable context) would be a problem for the cases where
>>> the delegate needs to alter some state (like export the result of some operation),
>>> but does _not_ modify the object it's embedded in. Note that the current object may
>>> very well be reachable (and mutable) from the delegate - but at some point you have
>>> to trust the programmer. Sure, fixing this hole would be great, but /how/ - w/o
>>> incurring unacceptable collateral damage?
>>>
>>
>> This isn't a problem as long as the delegate isn't a member of the object. If it is, transitivity is broken, which is something you don't want.
>>
>> Relying on the trust on the programmer is a dumb idea. Human do mistake, way more than computers. The basic behavior MUST be a safe one.
>>
>> Transitivity has been introduced for good reason and language already provide a way to break it via cast. So it is unacceptable to rely on programmer on that point.
>>
>>>> It is possible to get the error when trying to call the delegate instead of preventing to make it const, as I said in the post you quote. It is probably a better solution.
>>>
>>> Any delegate?
>>>
>>
>> No, any delegate that have type that isn't covariant with the expected delegate type.
>
>     struct S {
>        int i; this(int i) { this.i = i; }
>        T* p;
>        void f(int i) { this.i = i; /*p.i++;*/ }
>     }
>     struct T {
>        int i; this(int i) { this.i = i; }
>        void delegate(int i) f;
>     }
>
>     void main() {
>        auto t = new T(42);
>        auto s = new S(17);
>        s.p = t;
>        t.f =&s.f;
>        f(t);
>     }
>
>     void f(const (T)* t) {
>        t.f(t.i*2);
>     }
>
> You're proposing to make the last 'f' function illegal, just because the
> commented out part could happen. I'm saying that this is unlikely to happen
> *by accident*, and of course would still be possible by casting away the
> constness.

I think you are overcomplicating things. Yes, the call would be illegal.

> But banning "unsafe" delegates would result in casts *when using "safe" ones*
> - which is not a real improvement because this would make the "bad" casts much
> harder to spot.
>

I think you don't understand the benefice of transitive type qualifier.