July 11, 2005
"Ben Hinkle" <Ben_member@pathlink.com> wrote in message news:dadu5k$1ei$1@digitaldaemon.com...
> >1) Reasonable model of "costness"
>
> Do what Walter suggested for 'in' plus 3 things: 1) 'out' return values 2)
> 'final' local variables and 3) make violations warn and not error. I think
> it
> should be a warning because mixing final/non-final is roughly like passing
> a
> signed int to an unsigned int - something fishy is going on but we'll
> assume the
> user knows what they are doing until they ask for our advice. In case it
> isn't
> obvious an explicit out return value means the output shouldn't be
> modified by
> the caller (ie assign it to a final variable or an in parameter). A final
> local
> variable is "deep immutable".
>
>>2) Notation. E.g. how readonly slice will look like
>>     in code. Function parameters, etc.
>
> void foo(in char[] str); // Walter's idea
> out char[] foo(); // means output is read-only
> final char[] str = "blah"; // str is read-only
>
>>3) How to avoid "clutter". This term appears here
>>     not once - means that it is reasonable - so
>>     we need to deal with it.
>
> Avoids clutter by making it a warning so you don't have to go nuts with
> final if
> you don't want to.

A variation on this is to just use the 'final' keyword and forget about
marking output values. So an input parameter, local variable or field marked
'final' means "deep immutable" in Walter's sense for the lifetime of that
variable. A final variable of array, pointer or reference type can be
assigned new values but the contents of the array, pointer or reference
(recursively) cannot change.
 void foo(final char[] str); // Walter's idea with 'final' instead of 'in'
 final char[] str = "blah"; // str contents are read-only
 struct Foo { final char[] str; }

If one really misses const outputs a 'final' output value can be spoofed by
transforming
 T foo();
to
 struct finalT{ final T x;}
 finalT foo();
although that would get annoying pretty quickly both to write, use and
maintain.


July 11, 2005
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:datvsm$1e46$1@digitaldaemon.com...
>
> "Ben Hinkle" <Ben_member@pathlink.com> wrote in message news:dadu5k$1ei$1@digitaldaemon.com...
>> >1) Reasonable model of "costness"
>>
>> Do what Walter suggested for 'in' plus 3 things: 1) 'out' return values
>> 2)
>> 'final' local variables and 3) make violations warn and not error. I
>> think it
>> should be a warning because mixing final/non-final is roughly like
>> passing a
>> signed int to an unsigned int - something fishy is going on but we'll
>> assume the
>> user knows what they are doing until they ask for our advice. In case it
>> isn't
>> obvious an explicit out return value means the output shouldn't be
>> modified by
>> the caller (ie assign it to a final variable or an in parameter). A final
>> local
>> variable is "deep immutable".
>>
>>>2) Notation. E.g. how readonly slice will look like
>>>     in code. Function parameters, etc.
>>
>> void foo(in char[] str); // Walter's idea
>> out char[] foo(); // means output is read-only
>> final char[] str = "blah"; // str is read-only
>>
>>>3) How to avoid "clutter". This term appears here
>>>     not once - means that it is reasonable - so
>>>     we need to deal with it.
>>
>> Avoids clutter by making it a warning so you don't have to go nuts with
>> final if
>> you don't want to.
>
> A variation on this is to just use the 'final' keyword and forget about
> marking output values. So an input parameter, local variable or field
> marked 'final' means "deep immutable" in Walter's sense for the lifetime
> of that variable. A final variable of array, pointer or reference type can
> be assigned new values but the contents of the array, pointer or reference
> (recursively) cannot change.
> void foo(final char[] str); // Walter's idea with 'final' instead of 'in'
> final char[] str = "blah"; // str contents are read-only
> struct Foo { final char[] str; }
>
> If one really misses const outputs a 'final' output value can be spoofed
> by transforming
> T foo();
> to
> struct finalT{ final T x;}
> finalT foo();
> although that would get annoying pretty quickly both to write, use and
> maintain.
>
>

Ben, am I correct thinking that your proposal

void foo(final char[] str); // Walter's idea with 'final' instead of 'in'
final char[] str = "blah"; // str contents are read-only
struct Foo { final char[] str; }

uses the same idea as in C++

void foo(const char[] str);
const char[] str = "blah";
struct Foo { const char[] str; }

but with different keyword?





July 11, 2005
> Ben, am I correct thinking that your proposal
>
> void foo(final char[] str); // Walter's idea with 'final' instead of 'in'
> final char[] str = "blah"; // str contents are read-only
> struct Foo { final char[] str; }
>
> uses the same idea as in C++
>
> void foo(const char[] str);
> const char[] str = "blah";
> struct Foo { const char[] str; }
>
> but with different keyword?

not exactly - see Walter's post about 'in'. Also in C++ const is a type modifier and here final would modify a variable like in Java. For information about Java's notion of final see http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.12.4 The difference from Java's final is that in Java final means the variable doesn't change but the array or object contents can change and here it would be the reverse - the variable can change but the contents can't. Other than that it's the same as Java's final :-)


July 11, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:dau6b2$1kuv$1@digitaldaemon.com...
>> Ben, am I correct thinking that your proposal
>>
>> void foo(final char[] str); // Walter's idea with 'final' instead of 'in'
>> final char[] str = "blah"; // str contents are read-only
>> struct Foo { final char[] str; }
>>
>> uses the same idea as in C++
>>
>> void foo(const char[] str);
>> const char[] str = "blah";
>> struct Foo { const char[] str; }
>>
>> but with different keyword?
>
> not exactly - see Walter's post about 'in'. Also in C++ const is a type
> modifier and here final would modify a variable like in Java. For
> information about Java's notion of final see
> http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.12.4
> The difference from Java's final is that in Java final means the variable
> doesn't change but the array or object contents can change and here it
> would be the reverse - the variable can change but the contents can't.
> Other than that it's the same as Java's final :-)

Hmm, it seems that we are speaking about the same entity but using different terms.

See, in C++ declaration of const variable like

const typename v;

means declaration of variable of "const typename" - implicitly generated
type - const version
of typename with all non const members disabled ( non availble ) for use
through 'v' alias.

Therefore, if I understand you and Walter correctly

C++:
      void foo(const char[] str)

is exactly yours:
      void foo(final char[] str)

and Walter's:
      void foo(in char[] str)

Is this correct?

Andrew.





July 11, 2005
> Hmm, it seems that we are speaking about the same entity but using different terms.
>
> See, in C++ declaration of const variable like
>
> const typename v;
>
> means declaration of variable of "const typename" - implicitly generated
> type - const version
> of typename with all non const members disabled ( non availble ) for use
> through 'v' alias.
>
> Therefore, if I understand you and Walter correctly
>
> C++:
>      void foo(const char[] str)
>
> is exactly yours:
>      void foo(final char[] str)
>
> and Walter's:
>      void foo(in char[] str)
>
> Is this correct?

Not as I read Walter's posts like http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/26096. In particular C++ const says nothing about changing the values through other references while this final/in proposal would assert that the value remains constant through all references. That's been the drum-beat of all these posts saying why D doesn't have const already. I don't understand the confusion here.

In addition the final/in proposal is different than C++ const for the
following example:
  struct A {
    A* ptr;
  }
  void foo(final A* ptr2) {
    ptr2.ptr.ptr = null; // illegal
  }
  void main() {
    A a;
    a.ptr = &a;
    foo(&a);
  }
vs in C++
  struct A {
    A* ptr;
  }
  void foo(const A* ptr2) {
    ptr2->ptr->ptr = 0; // legal
  }
  void main() {
    A a;
    a.ptr = &a;
    foo(&a);
  }
The example is simplistic but it illustrates the meaning of recursive/deep
immutability.


July 11, 2005
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:daubr5$1phd$1@digitaldaemon.com...
>> Hmm, it seems that we are speaking about the same entity but using different terms.
>>
>> See, in C++ declaration of const variable like
>>
>> const typename v;
>>
>> means declaration of variable of "const typename" - implicitly generated
>> type - const version
>> of typename with all non const members disabled ( non availble ) for use
>> through 'v' alias.
>>
>> Therefore, if I understand you and Walter correctly
>>
>> C++:
>>      void foo(const char[] str)
>>
>> is exactly yours:
>>      void foo(final char[] str)
>>
>> and Walter's:
>>      void foo(in char[] str)
>>
>> Is this correct?
>
> Not as I read Walter's posts like http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/26096. In particular C++ const says nothing about changing the values through other references while this final/in proposal would assert that the value remains constant through all references. That's been the drum-beat of all these posts saying why D doesn't have const already. I don't understand the confusion here.

Practical "ultimate resource immutability" ( a.k.a.
"Andrei's deep immutability" ) implementation is not feasible on compiler
level for
langages of D class (e.g. having pointers).
Only on VM level it is possible to do it and at some extent only. As
"D virtual machine" is a processor itself then it means that without
os/hardware support implementation of this dream is not possible.
I though that it was clear from the very beginning....

BTW: Do you know any solution for read-only protection
of any arbitrary memory location?
Highly probable that I missed something in this area recently.

>
> In addition the final/in proposal is different than C++ const for the
> following example:
>  struct A {
>    A* ptr;
>  }
>  void foo(final A* ptr2) {
>    ptr2.ptr.ptr = null; // illegal
>  }
>  void main() {
>    A a;
>    a.ptr = &a;
>    foo(&a);
>  }

> vs in C++
>  struct A {
>    A* ptr;
>  }
>  void foo(const A* ptr2) {
>    ptr2->ptr->ptr = 0; // legal
>  }

True. I think that C++ behavior in this case can be better as if you would change this to:

struct A {
  A *_ptr;
  A* ptr() { return _ptr; }
};

void foo(const A* ptr2) {
   ptr2->ptr()->ptr(); // error here
}

you will get an error:
'ptr' : cannot convert 'this' pointer from 'const struct A' to 'struct A &'
or so.

>  void main() {
>    A a;
>    a.ptr = &a;
>    foo(&a);
>  }
> The example is simplistic but it illustrates the meaning of recursive/deep
> immutability.

Yes it is. As I have shown in example above C++ does
such deep immutability.

I am using "deep immutability" term as it is described here: http://www-sop.inria.fr/everest/events/cassis05/Transp/poll.pdf page #18



July 11, 2005
"Andrew Fedoniouk" <news@terrainformatica.com> wrote in message news:daui3u$1vos$1@digitaldaemon.com...
>
> "Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:daubr5$1phd$1@digitaldaemon.com...
>>> Hmm, it seems that we are speaking about the same entity but using different terms.
>>>
>>> See, in C++ declaration of const variable like
>>>
>>> const typename v;
>>>
>>> means declaration of variable of "const typename" - implicitly generated
>>> type - const version
>>> of typename with all non const members disabled ( non availble ) for use
>>> through 'v' alias.
>>>
>>> Therefore, if I understand you and Walter correctly
>>>
>>> C++:
>>>      void foo(const char[] str)
>>>
>>> is exactly yours:
>>>      void foo(final char[] str)
>>>
>>> and Walter's:
>>>      void foo(in char[] str)
>>>
>>> Is this correct?
>>
>> Not as I read Walter's posts like http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/26096. In particular C++ const says nothing about changing the values through other references while this final/in proposal would assert that the value remains constant through all references. That's been the drum-beat of all these posts saying why D doesn't have const already. I don't understand the confusion here.
>
> Practical "ultimate resource immutability" ( a.k.a.
> "Andrei's deep immutability" ) implementation is not feasible on compiler
> level for
> langages of D class (e.g. having pointers).
> Only on VM level it is possible to do it and at some extent only. As
> "D virtual machine" is a processor itself then it means that without
> os/hardware support implementation of this dream is not possible.
> I though that it was clear from the very beginning....
>
> BTW: Do you know any solution for read-only protection
> of any arbitrary memory location?
> Highly probable that I missed something in this area recently.

As Walter's original post said deep immutability is a contract made by the programmer to the compiler (and other programmers) which the compiler can verify in simple cases similar to the cases C++ const would catch. It is independent of any VM or the existence of pointers. Are you trying to say the contract must be verfied in *all* cases? I agree it is impractical to validate all cases. I suspect that's why Walter said the compiler would only catch simple cases like assigning through an immutable pointer and such.

>>
>> In addition the final/in proposal is different than C++ const for the
>> following example:
>>  struct A {
>>    A* ptr;
>>  }
>>  void foo(final A* ptr2) {
>>    ptr2.ptr.ptr = null; // illegal
>>  }
>>  void main() {
>>    A a;
>>    a.ptr = &a;
>>    foo(&a);
>>  }
>
>> vs in C++
>>  struct A {
>>    A* ptr;
>>  }
>>  void foo(const A* ptr2) {
>>    ptr2->ptr->ptr = 0; // legal
>>  }
>
> True. I think that C++ behavior in this case can be better as if you would change this to:
>
> struct A {
>  A *_ptr;
>  A* ptr() { return _ptr; }
> };
>
> void foo(const A* ptr2) {
>   ptr2->ptr()->ptr(); // error here
> }
>
> you will get an error:
> 'ptr' : cannot convert 'this' pointer from 'const struct A' to 'struct A
> &' or so.
>
>>  void main() {
>>    A a;
>>    a.ptr = &a;
>>    foo(&a);
>>  }
>> The example is simplistic but it illustrates the meaning of
>> recursive/deep immutability.
>
> Yes it is. As I have shown in example above C++ does
> such deep immutability.

Sure - if you change the C++ example to not allow any writing then it becomes immutable. But that is different than what I originally posted and what Walter meant by deep immutable parameter.

> I am using "deep immutability" term as it is described here: http://www-sop.inria.fr/everest/events/cassis05/Transp/poll.pdf page #18

I understand. Do you understand Walter's description of deep immutability from his post? The key phrase in Walter's post is "every sub-object reachable from that parameter". Perhaps we should start using the phrases "deep immutable type" and "deep immutable variable" to distinguish between the notions.


July 11, 2005
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:daul84$229o$1@digitaldaemon.com...
>
> "Andrew Fedoniouk" <news@terrainformatica.com> wrote in message news:daui3u$1vos$1@digitaldaemon.com...
>>
>> "Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:daubr5$1phd$1@digitaldaemon.com...
>>>> Hmm, it seems that we are speaking about the same entity but using different terms.
>>>>
>>>> See, in C++ declaration of const variable like
>>>>
>>>> const typename v;
>>>>
>>>> means declaration of variable of "const typename" - implicitly
>>>> generated type - const version
>>>> of typename with all non const members disabled ( non availble ) for
>>>> use through 'v' alias.
>>>>
>>>> Therefore, if I understand you and Walter correctly
>>>>
>>>> C++:
>>>>      void foo(const char[] str)
>>>>
>>>> is exactly yours:
>>>>      void foo(final char[] str)
>>>>
>>>> and Walter's:
>>>>      void foo(in char[] str)
>>>>
>>>> Is this correct?
>>>
>>> Not as I read Walter's posts like http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/26096. In particular C++ const says nothing about changing the values through other references while this final/in proposal would assert that the value remains constant through all references. That's been the drum-beat of all these posts saying why D doesn't have const already. I don't understand the confusion here.
>>
>> Practical "ultimate resource immutability" ( a.k.a.
>> "Andrei's deep immutability" ) implementation is not feasible on compiler
>> level for
>> langages of D class (e.g. having pointers).
>> Only on VM level it is possible to do it and at some extent only. As
>> "D virtual machine" is a processor itself then it means that without
>> os/hardware support implementation of this dream is not possible.
>> I though that it was clear from the very beginning....
>>
>> BTW: Do you know any solution for read-only protection
>> of any arbitrary memory location?
>> Highly probable that I missed something in this area recently.
>
> As Walter's original post said deep immutability is a contract made by the programmer to the compiler (and other programmers) which the compiler can verify in simple cases similar to the cases C++ const would catch. It is independent of any VM or the existence of pointers. Are you trying to say the contract must be verfied in *all* cases? I agree it is impractical to validate all cases. I suspect that's why Walter said the compiler would only catch simple cases like assigning through an immutable pointer and such.

I suspect quite opposite:

Walter:
"On the other hand, look at C++ "const". Nothing about "const" says that
some
other thread or reference cannot change the value out from under you at any
moment. Furthermore, it can be cast away and modified anyway. The semantic
value of C++ "const" is essentially zip. This is why I am often flummoxed
why it is given such weight in C++."

Ben: "Are you trying to say the contract must be verfied in *all* cases?"
Of course no. This is Walter who is trying to say this as far as I
understand his concerns
about 'const' in C++.

>
>>>
>>> In addition the final/in proposal is different than C++ const for the
>>> following example:
>>>  struct A {
>>>    A* ptr;
>>>  }
>>>  void foo(final A* ptr2) {
>>>    ptr2.ptr.ptr = null; // illegal
>>>  }
>>>  void main() {
>>>    A a;
>>>    a.ptr = &a;
>>>    foo(&a);
>>>  }
>>
>>> vs in C++
>>>  struct A {
>>>    A* ptr;
>>>  }
>>>  void foo(const A* ptr2) {
>>>    ptr2->ptr->ptr = 0; // legal
>>>  }
>>
>> True. I think that C++ behavior in this case can be better as if you would change this to:
>>
>> struct A {
>>  A *_ptr;
>>  A* ptr() { return _ptr; }
>> };
>>
>> void foo(const A* ptr2) {
>>   ptr2->ptr()->ptr(); // error here
>> }
>>
>> you will get an error:
>> 'ptr' : cannot convert 'this' pointer from 'const struct A' to 'struct A
>> &' or so.
>>
>>>  void main() {
>>>    A a;
>>>    a.ptr = &a;
>>>    foo(&a);
>>>  }
>>> The example is simplistic but it illustrates the meaning of
>>> recursive/deep immutability.
>>
>> Yes it is. As I have shown in example above C++ does
>> such deep immutability.
>
> Sure - if you change the C++ example to not allow any writing then it becomes immutable. But that is different than what I originally posted and what Walter meant by deep immutable parameter.
>
>> I am using "deep immutability" term as it is described here: http://www-sop.inria.fr/everest/events/cassis05/Transp/poll.pdf page #18
>
> I understand. Do you understand Walter's description of deep immutability from his post? The key phrase in Walter's post is "every sub-object reachable from that parameter". Perhaps we should start using the phrases "deep immutable type" and "deep immutable variable" to distinguish between the notions.
>

Yes, I think I understand "every sub-object reachable from that parameter".
This is exactly referentional deep immutability -
"using this particular reference to the object it is impossible to change
state of the object and every sub-object reachable from that object"

This is what C++ and Javari are doing:

"The specific constraint expressed is that the abstract state of the object
to which an immutable reference refers cannot be modified using that
reference. The abstract state is (part of) the transitively reachable state:
that is, the state of the object and all state reachable from it by
following references. The type system permits explicitly excluding fields or
objects from the abstract state of an object. For a statically type-safe
language, the type system guarantees reference immutability."
Javari also allows to:
"If the language is extended with immutability downcasts, then run-time
checks enforce the reference immutability constraints."
by making specific changes in VM.

C++ is using 'const' and Javari uses 'readonly' for marking parameters, fields and methods. http://pag.csail.mit.edu/~mernst/pubs/ref-immutability-oopsla2004-slides.pdf http://pag.csail.mit.edu/~mernst/pubs/ref-immutability-oopsla2004.pdf






July 11, 2005
On Mon, 11 Jul 2005 16:09:37 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
> Yes, I think I understand "every sub-object reachable from that parameter".
> This is exactly referentional deep immutability -
> "using this particular reference to the object it is impossible to change
> state of the object and every sub-object reachable from that object"
>
> This is what C++ and Javari are doing:

Doesn't this example:

  struct A {
    A* ptr;
  }
  void foo(const A* ptr2) {
    ptr2->ptr->ptr = 0; // legal
  }
  void main() {
    A a;
    a.ptr = &a;
    foo(&a);
  }

show that C++ const does not (by default) protect sub-objects, instead a re-design (as you posted) to also use a getter is required.

Walters 'in'/'final' deep immutable idea would not require the getter (if I understand it correctly) and so is surely superior?

Regan
July 11, 2005
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opstru1ah323k2f5@nrage.netwin.co.nz...
> On Mon, 11 Jul 2005 16:09:37 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>> Yes, I think I understand "every sub-object reachable from that
>> parameter".
>> This is exactly referentional deep immutability -
>> "using this particular reference to the object it is impossible to change
>> state of the object and every sub-object reachable from that object"
>>
>> This is what C++ and Javari are doing:
>
> Doesn't this example:
>
>   struct A {
>     A* ptr;
>   }
>   void foo(const A* ptr2) {
>     ptr2->ptr->ptr = 0; // legal
>   }
>   void main() {
>     A a;
>     a.ptr = &a;
>     foo(&a);
>   }
>
> show that C++ const does not (by default) protect sub-objects, instead a re-design (as you posted) to also use a getter is required.

As far as I recall it was some rationale behind this. I'll try to find.
In any case implementation of this approach will end up with marking
parameters, fields and methods by 'const' or 'readonly'.
This is what is being considered by Walter as "cluttering" (I personally
don't think so)

>
> Walters 'in'/'final' deep immutable idea would not require the getter (if I understand it correctly) and so is surely superior?
>
> Regan