June 18, 2012
On 6/18/12 2:14 AM, Mehrdad wrote:
> 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);
> }

Yes. Currently the constructor is not typechecked properly. Kenji has done some work on that and is still blocked by me and Walter with some questions.

Andrei
June 18, 2012
On Monday, 18 June 2012 at 14:37:26 UTC, Andrei Alexandrescu wrote:
> On 6/18/12 1:35 AM, Matthias Walter wrote:
>> On 06/18/2012 08:19 AM, Mehrdad wrote:
>>> On Monday, 18 June 2012 at 06:14:22 UTC, Matthias Walter wrote:
>>>> Its not, that a const method cannot modify an object, it just
>>>> ensures that the const method cannot modify the object *by using
>>>> the this-pointer*.
>>>
>>>
>>>
>>> I see...
>>>
>>>
>>> So that means you /can't/ tell something just by looking at a part
>>> of the code, right?
>>>
>>> (Just mentioning this since this idea seemed to be emphasized a lot
>>> by D.)
>>
>> Yes, you are right with that.
>
> Actually things are a fair amount subtler. On the face of it, immutable does fulfill the OP's expectation. But even for const code, there's still a lot of guarantees that can be inferred depending on the types involved.
>
> Andrei

Changing "new const(S)(0);" to "new immutable(S)(0);" still doesn't work tho.
June 18, 2012
Le 18/06/2012 16:28, Artur Skawina a écrit :
> It's fine, if you view a delegate as opaque.
>

No it isn't. You cannot ensure transitivity anywhere. This have obvious, and severe drawback for concurrent programing (implicit sharing is back) and GC performances (GC can eb crazy fast when it come to transitive immutable data, see OCaml's GC performances for instance).

> 'this' being const does not preclude accessing the object that 'this'
> points to via another, mutable, reference.
>
> Consider the alternative - you'd have to forbid storing any delegate
> with a non-const non-value argument inside any object.
>
> And "breaking" const would then _still_ be possible and trivial.
>

No, and your example don't demonstrate that in any way. Transitivity is maintained in the example below, because g isn't a member of s, and if it were, then the example would break at compile time.

>     import std.stdio;
>
>     S*[const(S)*] g;
>
>     struct S {
>        int i;
>        this(int i) { this.i = i; g[&this] =&this; }
>        void f() const { g[&this].i=666; }
>     }
>
>     void main() {
>        const s = S(42);
>        writeln(s);
>        s.f();
>        writeln(s);
>     }
>
> Yes, D's "pure" could help here, only it's misnamed (even if in
> this particular case that term would be fitting).
>

purity is another beast altogether.
June 18, 2012
On Monday, 18 June 2012 at 12:43:04 UTC, deadalnix wrote:
> Le 18/06/2012 07:36, Mehrdad a écrit :
>> Is it just me, or did I subvert the type system here?
>>
>
> delegate fail to ensure transitivity of type qualifier. This is no news. This is however a big error.


Oh lol :( thought I'd discovered something.

Well in that case, shouldn't the system protect itself then?

Otherwise it seems like 'const' in D becomes just like C++ const (doesn't let you "prove" anything)...


> I proposed a fix to that by changing the semantic of the type qualifier depending on its position in the declaration, but didn't received much feedback at the time.

Interesting!
June 18, 2012
On 6/18/12 7:43 AM, deadalnix wrote:
> Le 18/06/2012 07:36, Mehrdad a écrit :
>> Is it just me, or did I subvert the type system here?
>>
>
> delegate fail to ensure transitivity of type qualifier. This is no news.
> This is however a big error.
>
> I proposed a fix to that by changing the semantic of the type qualifier
> depending on its position in the declaration, but didn't received much
> feedback at the time.

I don't think that's the correct explanation.

Andrei

June 18, 2012
On Monday, 18 June 2012 at 14:41:02 UTC, deadalnix wrote:
> Le 18/06/2012 16:28, Artur Skawina a écrit :
>> It's fine, if you view a delegate as opaque.
>>
>
> No it isn't. You cannot ensure transitivity anywhere. This have obvious, and severe drawback for concurrent programing (implicit sharing is back) and GC performances (GC can eb crazy fast when it come to transitive immutable data, see OCaml's GC performances for instance).
>
>> 'this' being const does not preclude accessing the object that 'this'
>> points to via another, mutable, reference.
>>
>> Consider the alternative - you'd have to forbid storing any delegate
>> with a non-const non-value argument inside any object.
>>
>> And "breaking" const would then _still_ be possible and trivial.
>>
>
> No, and your example don't demonstrate that in any way. Transitivity is maintained in the example below, because g isn't a member of s, and if it were, then the example would break at compile time.
>
>>    import std.stdio;
>>
>>    S*[const(S)*] g;
>>
>>    struct S {
>>       int i;
>>       this(int i) { this.i = i; g[&this] =&this; }
>>       void f() const { g[&this].i=666; }
>>    }
>>
>>    void main() {
>>       const s = S(42);
>>       writeln(s);
>>       s.f();
>>       writeln(s);
>>    }
>>
>> Yes, D's "pure" could help here, only it's misnamed (even if in
>> this particular case that term would be fitting).
>>
>
> purity is another beast altogether.



Interesting, making the delegate `pure' doesn't change anything either.

So 'pure' doesn't let you "infer something just by looking at the code either", right?
June 18, 2012
Le 18/06/2012 16:43, Andrei Alexandrescu a écrit :
> On 6/18/12 7:43 AM, deadalnix wrote:
>> Le 18/06/2012 07:36, Mehrdad a écrit :
>>> Is it just me, or did I subvert the type system here?
>>>
>>
>> delegate fail to ensure transitivity of type qualifier. This is no news.
>> This is however a big error.
>>
>> I proposed a fix to that by changing the semantic of the type qualifier
>> depending on its position in the declaration, but didn't received much
>> feedback at the time.
>
> I don't think that's the correct explanation.
>
> Andrei
>

I fail to understand what you mean here. This post ins't supposed to explain anything. I've however made other posts to explain why transitivity is broken when it comes to delegate.
June 18, 2012
Le 18/06/2012 16:44, Mehrdad a écrit :
> Interesting, making the delegate `pure' doesn't change anything either.
>
> So 'pure' doesn't let you "infer something just by looking at the code
> either", right?

It does ! It tell you that the function have no side effect, and that the function called with identical arguments will return identical results.

pure will not ensure constness or immutability. const and immutable are made for that.

The fact that D decouple purity and immutability is a very nice design decision and is explained nicely here : http://klickverbot.at/blog/2012/05/purity-in-d/
June 18, 2012
On 6/18/12 9:45 AM, deadalnix wrote:
> Le 18/06/2012 16:43, Andrei Alexandrescu a écrit :
>> On 6/18/12 7:43 AM, deadalnix wrote:
>>> Le 18/06/2012 07:36, Mehrdad a écrit :
>>>> Is it just me, or did I subvert the type system here?
>>>>
>>>
>>> delegate fail to ensure transitivity of type qualifier. This is no news.
>>> This is however a big error.
>>>
>>> I proposed a fix to that by changing the semantic of the type qualifier
>>> depending on its position in the declaration, but didn't received much
>>> feedback at the time.
>>
>> I don't think that's the correct explanation.
>>
>> Andrei
>>
>
> I fail to understand what you mean here. This post ins't supposed to
> explain anything.

Mehrdad posted a code sample and you replied to it with what I could only assume was an explanation of the code's behavior. I hope you'd agree it was a reasonable assumption, whether or not it was correct.

The problem at work here is that "this" is typed incorrectly during the construction of a qualified object. It should go progressively from a
"raw" to a "cooked" state, and cannot be passed to any function while raw.

> I've however made other posts to explain why
> transitivity is broken when it comes to delegate.

I looked at your posts through June and couldn't find such, so a couple of links would be great. Of course, bug reports would be even better!


Andrei
June 18, 2012
On Monday, 18 June 2012 at 14:48:37 UTC, deadalnix wrote:
> Le 18/06/2012 16:44, Mehrdad a écrit :
>> Interesting, making the delegate `pure' doesn't change anything either.
>>
>> So 'pure' doesn't let you "infer something just by looking at the code
>> either", right?
>
> It does ! It tell you that the function have no side effect, and that the function called with identical arguments will return identical results.
>
> pure will not ensure constness or immutability. const and immutable are made for that.
>
> The fact that D decouple purity and immutability is a very nice design decision and is explained nicely here : http://klickverbot.at/blog/2012/05/purity-in-d/



Identical calls giving identical results? What?


import std.stdio;
struct S
{
         this(int a)
         {
                 this.a = a;
                 this.increment = { return this.a++; };
         }
         int a;
         int delegate() pure increment;
         auto oops() const { return this.increment(); }
}
void main()
{
         auto c = immutable(S)(0);
         writeln(c.oops()); // 0
         writeln(c.oops()); // 1
         writeln(c.oops()); // 2
         writeln(c.oops()); // 3
         writeln(c.oops()); // 4
         writeln(c.oops()); // 5
}