www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - invariant/const class storage class

reply Nicolas Sicard <dransic free.fr> writes:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body bgcolor=3D"#ffffff
Hi,<br>
I had a look at <a class=3D"moz-txt-link-freetext" href=3D"http://www.dig=
italmars.com/d/2.0/class.html#ConstClass">http://www.digitalmars.com/d/2.=
0/class.html#ConstClass</a>.<br>
Does this mean that I should be able to write something like :<br>
<blockquote><tt>module test;<br>
  <br>
invariant class Thing {<br>
=C2=A0=C2=A0=C2=A0 private int _field;<br>
  <br>
=C2=A0=C2=A0=C2=A0 this(int field) {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 _field =3D field;<br>
=C2=A0=C2=A0=C2=A0 }<br>
  <br>
=C2=A0=C2=A0=C2=A0 int field() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return _field;<br>
=C2=A0=C2=A0=C2=A0 }<br>
}</tt><br>
</blockquote>
?<br>
It doesn't compile:<br>
<blockquote><tt>Error: cannot implicitly convert expression (this) of
type invariant(Thing) to test.Thing</tt><br>
</blockquote>
The error doesn't mention any line. I don't undestand it. <br>
I thought it would be a way of saying that instances of a class are
always const or immutable.<br>
Sorry if I said something stupid <span class=3D"moz-smiley-s1"><span>
:-)=C2=A0 </span></span>...<br>
<br>
Nicolas<br>
</body>
</html>
Sep 30 2008
parent reply Neil Vice <sardonicpresence gmail.com> writes:
Nicolas Sicard wrote:
 Hi,
 I had a look at http://www.digitalmars.com/d/2.0/class.html#ConstClass.
 Does this mean that I should be able to write something like :
 
     module test;
 
     invariant class Thing {
         private int _field;
 
         this(int field) {
             _field = field;
         }
 
         int field() {
             return _field;
         }
     }
 
 ?
 It doesn't compile:
 
     Error: cannot implicitly convert expression (this) of type
     invariant(Thing) to test.Thing
 
 The error doesn't mention any line. I don't undestand it.
 I thought it would be a way of saying that instances of a class are 
 always const or immutable.
 Sorry if I said something stupid :-)  ...
 
 Nicolas
My understanding is that by applying a const/invariant specifier to a class type you are effectively indicating that its "this" reference has that specifier. So in this case, in the constructor where you attempt to assign to _field, you are attempting to modify an invariant "this" variable, which is not permitted. The compiler error message is due to it attempting to implicitly cast the invariant(Thing) to a non-invariant Thing in order to assign to its member. If my understanding is correct I am not sure how invariant classes would be useful as they could only have invariant fields and as such would seem to be sort of a collection of constants. Undoubtedly however, I will be corrected =P
Sep 30 2008
parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Wed, 01 Oct 2008 04:49:36 +0200, Neil Vice <sardonicpresence gmail.com>  
wrote:

 Nicolas Sicard wrote:
 Hi,
 I had a look at http://www.digitalmars.com/d/2.0/class.html#ConstClass.
 Does this mean that I should be able to write something like :
      module test;
      invariant class Thing {
         private int _field;
          this(int field) {
             _field = field;
         }
          int field() {
             return _field;
         }
     }
  ?
 It doesn't compile:
      Error: cannot implicitly convert expression (this) of type
     invariant(Thing) to test.Thing
  The error doesn't mention any line. I don't undestand it.
 I thought it would be a way of saying that instances of a class are  
 always const or immutable.
 Sorry if I said something stupid :-)  ...
  Nicolas
My understanding is that by applying a const/invariant specifier to a class type you are effectively indicating that its "this" reference has that specifier. So in this case, in the constructor where you attempt to assign to _field, you are attempting to modify an invariant "this" variable, which is not permitted. The compiler error message is due to it attempting to implicitly cast the invariant(Thing) to a non-invariant Thing in order to assign to its member. If my understanding is correct I am not sure how invariant classes would be useful as they could only have invariant fields and as such would seem to be sort of a collection of constants. Undoubtedly however, I will be corrected =P
Unless I've misunderstood, you are indeed correct. I also thought you'd be allowed to create invariant objects by using an invariant constructor, but that seems not to be the case. Is this really correct behavior? How then are we supposed to initialize our invariant objects? -- Simen
Oct 01 2008
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
Oct 01 2008
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2? I think it can work like this: class A { this(params) {} // [1] invariant this(params) {} // [2] } // create a mutable object - will use type [1] c-tors. auto a = new A(params); // create an invariant object - will use type [2] c-tors. invariant a = new A(params); // create a const object - will use type [1] or [2] c-tors. const a = new A(params); in the const case, if there are two c-tors which only differ by invariant-ness of the c-tor using either will create ambiguity and therefore should be a compile-time error.
Oct 01 2008
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:
 
 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }
 
 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);
 
 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);
 
 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);
 
 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
Oct 01 2008
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
May I ask what are the complications?
Oct 01 2008
parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Wed, 01 Oct 2008 16:23:32 +0200, Yigal Chripun <yigal100 gmail.com>  
wrote:

 Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
May I ask what are the complications?
"Mortis Portalis Tackulatum - and he's still breathing"... -- Simen
Oct 01 2008
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Simen Kjaeraas wrote:
 On Wed, 01 Oct 2008 16:23:32 +0200, Yigal Chripun <yigal100 gmail.com> 
 wrote:
 
 Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
May I ask what are the complications?
"Mortis Portalis Tackulatum - and he's still breathing"...
Tackulatum? Was that tacitum? Andrei
Oct 01 2008
parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 02 Oct 2008 03:46:00 +0200, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Simen Kjaeraas wrote:
 On Wed, 01 Oct 2008 16:23:32 +0200, Yigal Chripun <yigal100 gmail.com>  
 wrote:

 Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
May I ask what are the complications?
"Mortis Portalis Tackulatum - and he's still breathing"...
Tackulatum? Was that tacitum? Andrei
From Terry Pratchett's 'Pyramids'. Doctor: "Fairly straightforward. A case of mortis portalis tackulatum with complications." Chidder: "What's that mean?" Doctor: "In laymen's terms, he's as dead as a doornail." Chidder: "What are the complications?" Doctor: "He's still breathing." -- Simen
Oct 01 2008
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Simen Kjaeraas wrote:
 On Thu, 02 Oct 2008 03:46:00 +0200, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Simen Kjaeraas wrote:
 On Wed, 01 Oct 2008 16:23:32 +0200, Yigal Chripun 
 <yigal100 gmail.com> wrote:

 Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
May I ask what are the complications?
"Mortis Portalis Tackulatum - and he's still breathing"...
Tackulatum? Was that tacitum? Andrei
From Terry Pratchett's 'Pyramids'. Doctor: "Fairly straightforward. A case of mortis portalis tackulatum with complications." Chidder: "What's that mean?" Doctor: "In laymen's terms, he's as dead as a doornail." Chidder: "What are the complications?" Doctor: "He's still breathing."
Heh. Funny, but what's the link? Andrei
Oct 01 2008
parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 02 Oct 2008 03:54:02 +0200, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Simen Kjaeraas wrote:
 On Thu, 02 Oct 2008 03:46:00 +0200, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 Simen Kjaeraas wrote:
 On Wed, 01 Oct 2008 16:23:32 +0200, Yigal Chripun  
 <yigal100 gmail.com> wrote:

 Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
May I ask what are the complications?
"Mortis Portalis Tackulatum - and he's still breathing"...
Tackulatum? Was that tacitum? Andrei
From Terry Pratchett's 'Pyramids'. Doctor: "Fairly straightforward. A case of mortis portalis tackulatum with complications." Chidder: "What's that mean?" Doctor: "In laymen's terms, he's as dead as a doornail." Chidder: "What are the complications?" Doctor: "He's still breathing."
Heh. Funny, but what's the link? Andrei
Uhm, nothing really. Just this managed to slip past my nonsense filter at 4 in the morning. -- Simen
Oct 02 2008
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Simen Kjaeraas wrote:
 On Thu, 02 Oct 2008 03:54:02 +0200, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Simen Kjaeraas wrote:
 On Thu, 02 Oct 2008 03:46:00 +0200, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 Simen Kjaeraas wrote:
 On Wed, 01 Oct 2008 16:23:32 +0200, Yigal Chripun 
 <yigal100 gmail.com> wrote:

 Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
There are plans.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
Way, way, way more complicated than this. Andrei
May I ask what are the complications?
"Mortis Portalis Tackulatum - and he's still breathing"...
Tackulatum? Was that tacitum? Andrei
From Terry Pratchett's 'Pyramids'. Doctor: "Fairly straightforward. A case of mortis portalis tackulatum with complications." Chidder: "What's that mean?" Doctor: "In laymen's terms, he's as dead as a doornail." Chidder: "What are the complications?" Doctor: "He's still breathing."
Heh. Funny, but what's the link? Andrei
Uhm, nothing really. Just this managed to slip past my nonsense filter at 4 in the morning.
I kept on thinking of connections const/invariant -> rigor mortis. Andrei
Oct 02 2008
prev sibling next sibling parent reply Nicolas Sicard <dransic free.fr> writes:
Yigal Chripun a =C3=A9crit :
 I understand casting as breaking the type system. shouldn't there be a
 way to create invariant objects without the cast?
 an invariant constructor seems a good way to solve this. any plans on
 adding such a feature to D2?

 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a =3D new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a =3D new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a =3D new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
  =20
What should an invariant constructor do that a plain one don't, apart=20 from specifying immutability of the instance? This would mean you could create instances of different types from the=20 same class, which is also kind of breaking the type system, isn't it? But declaring a class invariant (for all instances) is something=20 interesting.
Oct 01 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
The different methods of making a class instance invariant basically depend 
on when the invariance applies.  For classes where the type is declared 
invariant, the invariant label is enforced after the memory is acquired and 
initialized, and before the constructor is called.  This doesn't seem to me 
to be a very useful construct.

Casting after the class is created makes the invariant label apply after the 
user has received the constructed class, but casting to invariant is up to 
the user.

BTW, casting to invariant is the only possible way to make useful invariant 
heap data.  One generates the data, then casts it to invariant.  Usually 
this is done with brand-new memory so there is no chance for some separate 
mutable reference to be formed.  The downside is that the assurance that the 
data is truly invariant is up to the developer.  The compiler has to take 
your word for it.

The proposed invariant constructors as defined in Andrei's functional 
document (don't have the pdf link handy, but it's on the digitalmars web 
site), I believe they had a section of code that you could set data, but 
once you started using the 'this' pointer as arguments to other functions, 
'this' implicitly switched to invariant.  I believe this would make 
invariant classes much more useful.

There is another alternative that works today.  A public static method that 
does this explicitly.  If you make the constructor private, then you can 
force the caller to use the public static method.  e.g.:

class X
{
   private this() {}
   public static invariant(X) makeInstance() { return cast(invariant(X)) new 
X();}
}

Now you can be assured that all instances of X are invariant, and you are 
free to assign data to members in the constructor, making X a useful 
construct.  It's slightly better than fully custom invariance (such as with 
Java Strings) in that the compiler and users of the class can make more 
assumptions, and not as much care needs to be taken in implementing such a 
class.

-Steve

"Nicolas Sicard" wrote
Yigal Chripun a écrit :
 I understand casting as breaking the type system. shouldn't there be a
 way to create invariant objects without the cast?
 an invariant constructor seems a good way to solve this. any plans on
 adding such a feature to D2?

 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }

 // create a mutable object - will use type [1] c-tors.
 auto a = new A(params);

 // create an invariant object - will use type [2] c-tors.
 invariant a = new A(params);

 // create a const object - will use type [1] or [2] c-tors.
 const a = new A(params);

 in the const case, if there are two c-tors which only differ by
 invariant-ness of the c-tor using either will create ambiguity and
 therefore should be a compile-time error.
What should an invariant constructor do that a plain one don't, apart from specifying immutability of the instance? This would mean you could create instances of different types from the same class, which is also kind of breaking the type system, isn't it? But declaring a class invariant (for all instances) is something interesting.
Oct 01 2008
parent Nicolas Sicard <dransic free.fr> writes:
Steven Schveighoffer a =C3=A9crit :
 The different methods of making a class instance invariant basically de=
pend=20
 on when the invariance applies.  For classes where the type is declared=
=20
 invariant, the invariant label is enforced after the memory is acquired=
and=20
 initialized, and before the constructor is called.  This doesn't seem t=
o me=20
 to be a very useful construct.
  =20
Ok now I understand the compiling error.
 Casting after the class is created makes the invariant label apply afte=
r the=20
 user has received the constructed class, but casting to invariant is up=
to=20
 the user.

 BTW, casting to invariant is the only possible way to make useful invar=
iant=20
 heap data.  One generates the data, then casts it to invariant.  Usuall=
y=20
 this is done with brand-new memory so there is no chance for some separ=
ate=20
 mutable reference to be formed.  The downside is that the assurance tha=
t the=20
 data is truly invariant is up to the developer.  The compiler has to ta=
ke=20
 your word for it.

 The proposed invariant constructors as defined in Andrei's functional=20
 document (don't have the pdf link handy, but it's on the digitalmars we=
b=20
 site), I believe they had a section of code that you could set data, bu=
t=20
 once you started using the 'this' pointer as arguments to other functio=
ns,=20
 'this' implicitly switched to invariant.  I believe this would make=20
 invariant classes much more useful.

 There is another alternative that works today.  A public static method =
that=20
 does this explicitly.  If you make the constructor private, then you ca=
n=20
 force the caller to use the public static method.  e.g.:

 class X
 {
    private this() {}
    public static invariant(X) makeInstance() { return cast(invariant(X)=
) new=20
 X();}
 }

 Now you can be assured that all instances of X are invariant, and you a=
re=20
 free to assign data to members in the constructor, making X a useful=20
 construct.  It's slightly better than fully custom invariance (such as =
with=20
 Java Strings) in that the compiler and users of the class can make more=
=20
 assumptions, and not as much care needs to be taken in implementing suc=
h a=20
 class.

 -Steve
  =20
Thanks for the explanations and the trick!
Oct 01 2008
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
Definitely. I can't imagine that the current situation is any more than an incomplete design. After all, everything needs to be initialized.
 I think it can work like this:
 
 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }
I don't see any point in having a separate 'invariant' ctor, given my point about initialization above. It should be perfectly legal to simply do: class A {} invariant a = new A; Just as it should be legal to do: string s = "a" ~ "b"; That both are illegal right now is ridiculous. Perhaps the "Polysemous Value" idea can apply here. Since the compiler can clearly detect that in both cases the value being assigned is not shared it should be perfectly acceptable to implicitly convert its type to a compatible but stronger type. Sean
Oct 01 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Sean Kelly" wrote
 Yigal Chripun wrote:
 Walter Bright wrote:
 Simen Kjaeraas wrote:
 Is this really correct behavior? How then are we supposed to
 initialize our
 invariant objects?
Currently, create them as mutable ones, then cast them to invariant.
I understand casting as breaking the type system. shouldn't there be a way to create invariant objects without the cast? an invariant constructor seems a good way to solve this. any plans on adding such a feature to D2?
Definitely. I can't imagine that the current situation is any more than an incomplete design. After all, everything needs to be initialized.
 I think it can work like this:

 class A {
   this(params) {}   // [1]
   invariant this(params) {}  // [2]
 }
I don't see any point in having a separate 'invariant' ctor, given my point about initialization above. It should be perfectly legal to simply do: class A {} invariant a = new A; Just as it should be legal to do: string s = "a" ~ "b"; That both are illegal right now is ridiculous. Perhaps the "Polysemous Value" idea can apply here. Since the compiler can clearly detect that in both cases the value being assigned is not shared it should be perfectly acceptable to implicitly convert its type to a compatible but stronger type.
What if the constructor for A stores a mutable reference to itself somewhere? Or even a mutable reference to one of it's members? This breaks the guarantee of transitive invariance, and the author of the constructor shouldn't need to worry about that. That's why I think we do need invariant constructors. BTW, I think you may have mistyped your string s = "a" ~ "b" example, that should be legal. -Steve
Oct 01 2008
parent Sean Kelly <sean invisibleduck.org> writes:
Steven Schveighoffer wrote:
 
 BTW, I think you may have mistyped your string s = "a" ~ "b" example, that 
 should be legal.
Oops, you're right. For compilation to fail, change it to: string s = "a".dup ~ "b"; Sean
Oct 01 2008