www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Constant relationships between non-constant objects

reply "Sebastian Unger" <sebunger44.remove gmail.com> writes:
Hi there,

I'm an experient C++ developer and am trying to switch to / learn
D. What I've seen so far is mostly quite straight forward and
VERY nice.

There's only one catch so far for me for which Googling has only
found the discouraging answer of: It can't be done in D.

I have two classes A and B. Each object of class A is associated
with a particular object of class B. This association is not
supposed to change throughout the lifetime of the object of A.

How am I supposed to express this in D, given that D's const is
too strong for this? I don't need any guarantees from the const
that can be used for thread safety or parallelisation. All I need
is the compiler not letting me change the reference to the B
object inside the A object.

Does D have some way of expressing this?

Or has D really done away with the MOST important use case of
const (preventing developer mistakes! Not optimization.)

Cheers,
Seb
Jun 17 2014
next sibling parent reply Justin Whear <justin economicmodeling.com> writes:
On Wed, 18 Jun 2014 01:31:32 +0000, Sebastian Unger wrote:

 Hi there,
 
 I'm an experient C++ developer and am trying to switch to / learn D.
 What I've seen so far is mostly quite straight forward and VERY nice.
 
 There's only one catch so far for me for which Googling has only found
 the discouraging answer of: It can't be done in D.
 
 I have two classes A and B. Each object of class A is associated with a
 particular object of class B. This association is not supposed to change
 throughout the lifetime of the object of A.
 
 How am I supposed to express this in D, given that D's const is too
 strong for this? I don't need any guarantees from the const that can be
 used for thread safety or parallelisation. All I need is the compiler
 not letting me change the reference to the B object inside the A object.
 
 Does D have some way of expressing this?
 
 Or has D really done away with the MOST important use case of const
 (preventing developer mistakes! Not optimization.)
 
 Cheers,
 Seb
I think you may be mixing up const and immutable. What do you mean about const being too strong? It seems that does what you want: class A { const B bff; this(B bestBuddy) { bff = bestBuddy; } }
Jun 17 2014
parent "Sebastian Unger" <sebunger44.remove gmail.com> writes:
On Wednesday, 18 June 2014 at 02:00:37 UTC, Justin Whear wrote:
 On Wed, 18 Jun 2014 01:31:32 +0000, Sebastian Unger wrote:

 Hi there,
 
 I'm an experient C++ developer and am trying to switch to / 
 learn D.
 What I've seen so far is mostly quite straight forward and 
 VERY nice.
 
 There's only one catch so far for me for which Googling has 
 only found
 the discouraging answer of: It can't be done in D.
 
 I have two classes A and B. Each object of class A is 
 associated with a
 particular object of class B. This association is not supposed 
 to change
 throughout the lifetime of the object of A.
 
 How am I supposed to express this in D, given that D's const 
 is too
 strong for this? I don't need any guarantees from the const 
 that can be
 used for thread safety or parallelisation. All I need is the 
 compiler
 not letting me change the reference to the B object inside the 
 A object.
 
 Does D have some way of expressing this?
 
 Or has D really done away with the MOST important use case of 
 const
 (preventing developer mistakes! Not optimization.)
 
 Cheers,
 Seb
I think you may be mixing up const and immutable. What do you mean about const being too strong? It seems that does what you want: class A { const B bff; this(B bestBuddy) { bff = bestBuddy; } }
You missed the point about A needing to modify B. I want to express a constant relationship between objects, not that A or B are constant. Cheers, Seb
Jun 17 2014
prev sibling next sibling parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger wrote:
 Or has D really done away with the MOST important use case of
 const (preventing developer mistakes! Not optimization.)

 Cheers,
 Seb
Yes. D does not provide head-const. Though I would disagree that it is the most important use-case for const.
Jun 17 2014
parent reply "Sebastian Unger" <sebunger44.remove gmail.com> writes:
On Wednesday, 18 June 2014 at 02:15:21 UTC, Jesse Phillips wrote:
 On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger 
 wrote:
 Or has D really done away with the MOST important use case of
 const (preventing developer mistakes! Not optimization.)

 Cheers,
 Seb
Yes. D does not provide head-const. Though I would disagree that it is the most important use-case for const.
But can you agree that it is AN important use case? If so, what was the rationale to not include a feature in D that has been used with great success in other languages? Don't get me wrong, I really like immutable and const and the fact that they are transitive. There are good use cases for this. But why NOT include head-const if there are also good use cases for it? Too afraid your users won't know the difference and use the wrong one? Well, that's counter productive because now the can't use any form of protection from the compiler in this (very valid and VERY prevalent) use case. I came across this a few hours into my very first small project using D. That tells you how common this use case is. I'd stronly argue for D getting that feature. If I can't express some of the most basic constructs in OOD in D, it really falls more into the category of a toy language for me. Cheers, Seb
Jun 17 2014
next sibling parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Wednesday, 18 June 2014 at 02:26:25 UTC, Sebastian Unger wrote:
 But can you agree that it is AN important use case?
I can't say I support this claim either.
 If so, what was the rationale to not include a feature in D 
 that has been used with great success in other languages?
D had 3 other const systems prior to its current state. This system provided the needed guarantees with the least complexity. Head-const would have added too much complexity for the benefit (almost nothing).
 I'd stronly argue for D getting that feature. If I can't 
 express some of the most basic constructs in OOD in D
Well, I always thought C++'s const was as described in this SO response http://stackoverflow.com/a/2736231/34435 "means this reference cannot be used to modify the instance" The problem being C++ did not enforce this rule and people started abusing it. And now they can't live without it. But my confession is that I am not and could not ever call myself a C++ programmer.
Jun 17 2014
parent reply "Sebastian Unger" <sebunger44.remove gmail.com> writes:
On Wednesday, 18 June 2014 at 03:36:54 UTC, Jesse Phillips wrote:
 On Wednesday, 18 June 2014 at 02:26:25 UTC, Sebastian Unger 
 wrote:
 If so, what was the rationale to not include a feature in D 
 that has been used with great success in other languages?
D had 3 other const systems prior to its current state. This system provided the needed guarantees with the least complexity. Head-const would have added too much complexity for the benefit (almost nothing).
Well, I think there is definitely benefit if you can tell the compiler that you don't mean to modify something and then the compiler will check this for you. Just think bugs like if (a = 3) ... instead of if (a == 3) ... Not sure if this particular bug is possible in D, but that's beside the point.
 I'd stronly argue for D getting that feature. If I can't 
 express some of the most basic constructs in OOD in D
Well, I always thought C++'s const was as described in this SO response http://stackoverflow.com/a/2736231/34435
That link has one problem: It states that const means different things to different people. That's not quite correct. There are different things I want to be const in different situations and I need my language to be able to express ALL of these with ease. Sometimes I want an object in flash memory and immutable is needed. Sometimes I want to pass it around between threads and transitive const is really useful. And sometimes I want a relationship to be const and D can't express that. People are just used to expressing these different conccepts using different mechanisms depending on the language they're using. But for D to be truly superior to other languages it needs to be able to express at least the same as these other languages. Basically what D is saying is, that every reference to an object from another object is a 'contains' relationship where transitive const makes sense. But that's simply not the real world of OOSD. In the real world there are many different types of relationships. And yes, sometimes I want an object to be located in ROM but have a reference to another object in RAM that I can modify. No way to express this in D.
 "means this reference cannot be used to modify the instance"
 The problem being C++ did not enforce this rule and people 
 started abusing it. And now they can't live without it.
Hang on, that's not entirely true. True, you could cast away const (if that is what you are referring to), but you can do the same in D. Other than that C++ (and in fact even C) enforced constness perfectly well: Without a cast it is not possible to modify that which is declared const. True, C(++) could not express the concept of immutable to the point where the compiler can assume an object is not changing as D can. But C(++) could easily enough express const relationships which D cannot express. Now, in the 19 years as a software developer, I have yet to come across a case where the (admittedly weaker) guarantees of C and C++ constness are simply not enough to express what I want to achieve. On the other hand, after beginning a small project as a test to see how D holds up, I came across the fact that D simply cannot express constant object relationships in a matter of hours. So from my experience it is clear which concept is the more important (to the projects I've been working on at least). But both are valid! So again, I believe, if D wants to play any role in major OO software design and development, it will need to step up its game. Especially in view of C++11 having addressed a number of the issues in C++ that I would have chosen D over C++ for. Cheers, Seb
Jun 17 2014
next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Wednesday, 18 June 2014 at 05:34:18 UTC, Sebastian Unger wrote:
 So again, I believe, if D wants to play any role in major OO 
 software design and development, it will need to step up its 
 game. Especially in view of C++11 having addressed a number of 
 the issues in C++ that I would have chosen D over C++ for.

 Cheers,
 Seb
I believe this is wrong. First of all, if you want to keep relationship between objects, instead of thinking which feature can prevent it, consider not to try to break it in a first place. Secondly, it is sometimes discussed how to write some idiomatic code per se, rather than to solve particular task. Thirdly, if feature from one language does not do the same as similar feature from other language, does not mean that the feature/language is broken. Lastly, taking into account that it was Walter decided to do so, says something. Regarding your problem. Keeping relationship between two classes can be achieved by associative array, by inheriting from one class or by using examples above.
Jun 17 2014
parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 18/06/2014 6:05 p.m., Maxim Fomin wrote:
 On Wednesday, 18 June 2014 at 05:34:18 UTC, Sebastian Unger wrote:
 So again, I believe, if D wants to play any role in major OO software
 design and development, it will need to step up its game. Especially
 in view of C++11 having addressed a number of the issues in C++ that I
 would have chosen D over C++ for.

 Cheers,
 Seb
I believe this is wrong. First of all, if you want to keep relationship between objects, instead of thinking which feature can prevent it, consider not to try to break it in a first place. Secondly, it is sometimes discussed how to write some idiomatic code per se, rather than to solve particular task. Thirdly, if feature from one language does not do the same as similar feature from other language, does not mean that the feature/language is broken.
+1
 Lastly, taking into account that it was Walter decided to do so, says
 something.

 Regarding your problem. Keeping relationship between two classes can be
 achieved by associative array, by inheriting from one class or by using
 examples above.
There is also always things like property getter functions if you really really want to be pedantic about it. class A { this(B b) { b_ = b; } private B b_; property B b() { return b_; } } class B { string text; this(string text) { this.text = text; } } void main() { import std.stdio; A a = new A(new B("hi there")); writeln(a.b.text); a.b.text = "boo"; writeln(a.b.text); } In this case, literally no way to get access to b_ variable directly unless you are in the same module. To prevent assignment within the same module, a wrapper would be needed as has been discussed. Personally I wouldn't use code like this. But thats just me.
Jun 17 2014
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Sebastian Unger:

 Just think bugs like
 if (a = 3) ...
 instead of
 if (a == 3) ...
 Not sure if this particular bug is possible in D, but that's 
 beside the point.
This bug is hard to do in D: void main() { int a = 3; if (a = 3) {} } test.d(3,14): Error: assignment cannot be used as a condition, perhaps == was meant?
 I'd stronly argue for D getting that feature. If I can't 
 express some of the most basic constructs in OOD in D, it 
 really falls more into the category of a toy language for me.
 Now, in the 19 years as a software developer,
When you are used to language A with feature X and you switch to language B that lacks X, a very common programmer's fallacy is to think you can't live with X or B is a toy language because it lacks X. In reality languages are not a collection of features, they are more like an ecology of features, where each part is designed keeping in account the presence of most of the other parts. So usually language B has features or tools that make up for the lack of X, or X was too much costly to add to B. So when you switch to use language B you need to adapt yourself and work around the lack of X using what B offers. Bye, bearophile
Jun 18 2014
prev sibling next sibling parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Jun 18, 2014 at 02:26:24AM +0000, Sebastian Unger via Digitalmars-d
wrote:
[...]
 But why NOT include head-const if there are also good use cases for
 it?
Because it can be easily emulated? Here's a working, first stab at it: ----- headconst.d ----- module headconst; struct HeadConst(T) { private T impl; property T get() { return impl; } alias get this; // magic ;-) this(T t) { impl = t; } // This is what stops rebinding void opAssign(T)(T) { static assert(false, "Cannot assign to HeadConst"); } } ------------------ ----- test.d ----- import headconst; unittest { class MyOtherClass { int x = 123; } class MyClass { HeadConst!MyOtherClass other; this() { other = HeadConst!MyOtherClass(new MyOtherClass); } } auto obj = new MyClass; // You can freely access the MyOtherClass instance in MyClass: assert(obj.other.x == 123); // And freely modify it: obj.other.x++; assert(obj.other.x == 124); // But you can't rebind it: //obj.other = new MyOtherClass; // error: cannot assign to HeadConst } void main() {} ------------------ Of course, there are some holes in the current implementation that need to be patched up, but this should get you started. Hope this helps. :) T -- Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
Jun 17 2014
prev sibling parent Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Wed, 18 Jun 2014 02:26:24 +0000
Sebastian Unger via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 On Wednesday, 18 June 2014 at 02:15:21 UTC, Jesse Phillips wrote:
 On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger
 wrote:
 Or has D really done away with the MOST important use case of
 const (preventing developer mistakes! Not optimization.)

 Cheers,
 Seb
Yes. D does not provide head-const. Though I would disagree that it is the most important use-case for const.
But can you agree that it is AN important use case?
It would be better to have it as an option, but in my experience, head-const is close to useless, so while it might be nice to have upon occasion, not having it isn't all that big a loss. I always thought that it was pretty useless that Java provided head-const (especially because that's the _only_ kind of const that it has).
 If so, what was the rationale to not include a feature in D that has been
 used with great success in other languages? Don't get me wrong, I
 really like immutable and const and the fact that they are
 transitive. There are good use cases for this.
It comes down to the same reason that we have std.typecons.Rebindable to make it so that you can have a non-const reference to a const object. The type system doesn't really have the concept of a class, just a class reference. When you say MyClass c; the type of MyClass is a reference to the class that's named MyClass rather than being MyClass itself, and there's nowhere in the type system that makes the distinction, because there's nowhere that you can even refer to a class type without a reference to an object of that class type. When const was first being worked on in D2, other options were explored with regards to how to handle const, and for a short while we had a distinction between head-const and tail-const when declaring variables of various types, but it was ultimately decided that the result was just too complicated, and the current route of using parens was introduced, which does lose us some flexibility, but it gets us most of the way there while being much simpler. However, I don't know think we ever really had head-const or tail-const classes even then, because of how classes are represented in the compiler. Walter attempted to rectify the problem multiple times but gave up on it, since apparently, it's quite difficult, and he got sick of trying. At least one major attempt has been made by another developer, but Walter didn't approve of the way that it was done, so it never made it into the compiler or the language (I don't know what the problems with it were though). So, to fix this, we'd need a way (syntactically) to somehow indicate that a class reference is head-const or tail-const without adding much complication to the language, and there would have to be a major overhaul of how classes are viewed by the compiler, which is enough of a pain that it's just never been fully, successfully done. So, we have std.typecons.Rebindable in order to get tail-const class references, and elsewhere in this thread, Meta provided a similar wrapper to give you head-const. However, no one has ever found head-const to be important enough to put anything like that in Phobos. It's always the lack of tail-const class references that folks complain about. You're the only person I've ever seen who's complained about the lack of head-const. - Jonathan M Davis
Jun 17 2014
prev sibling next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger wrote:
 Hi there,

 I'm an experient C++ developer and am trying to switch to / 
 learn
 D. What I've seen so far is mostly quite straight forward and
 VERY nice.

 There's only one catch so far for me for which Googling has only
 found the discouraging answer of: It can't be done in D.

 I have two classes A and B. Each object of class A is associated
 with a particular object of class B. This association is not
 supposed to change throughout the lifetime of the object of A.

 How am I supposed to express this in D, given that D's const is
 too strong for this? I don't need any guarantees from the const
 that can be used for thread safety or parallelisation. All I 
 need
 is the compiler not letting me change the reference to the B
 object inside the A object.

 Does D have some way of expressing this?

 Or has D really done away with the MOST important use case of
 const (preventing developer mistakes! Not optimization.)

 Cheers,
 Seb
There's no head const in D, but you can emulate it. This is a *very* basic example that you can expand upon. http://dpaste.dzfl.pl/55cb22153fcc
Jun 17 2014
parent reply "Sebastian Unger" <sebunger44.remove gmail.com> writes:
On Wednesday, 18 June 2014 at 04:38:25 UTC, Meta wrote:
 On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger 
 wrote:
 There's no head const in D, but you can emulate it. This is a 
 *very* basic example that you can expand upon.

 http://dpaste.dzfl.pl/55cb22153fcc
Thanks for that link. Yes, that is close. I'd even feel reasonaly well about it if it was in phobos so everybody can use the mechanism consistently. It does not however, quite meet the mark of "with ease". But it is possibly an acceptable hack around a shortcoming in the language. Comming from C++, it's not as though I'm not used to those. Just a shame to have to resort to it when D is so pretty close to getting rid of dirty hacks more or less completely. Cheers, Seb
Jun 17 2014
next sibling parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Jun 18, 2014 at 05:40:47AM +0000, Sebastian Unger via Digitalmars-d
wrote:
 On Wednesday, 18 June 2014 at 04:38:25 UTC, Meta wrote:
On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger wrote:
There's no head const in D, but you can emulate it. This is a *very* basic
example that you can expand upon.

http://dpaste.dzfl.pl/55cb22153fcc
Thanks for that link. Yes, that is close. I'd even feel reasonaly well about it if it was in phobos so everybody can use the mechanism consistently.
Pull requests are always welcome. ;-)
 It does not however, quite meet the mark of "with ease".
Why not? You can just put it in its module and import it whenever you need it.
 But it is possibly an acceptable hack around a shortcoming in the
 language.
 Comming from C++, it's not as though I'm not used to those.
 Just a shame to have to resort to it when D is so pretty close to
 getting rid of dirty hacks more or less completely.
[...] I don't see it as a hack, much less a dirty one. The language was designed precisely to allow implementing this kind of user-defined extensions easily. In fact, there has been a recent trend to move things *out* of the core language where a library implementation suffices. T -- Computers are like a jungle: they have monitor lizards, rams, mice, c-moss, binary trees... and bugs.
Jun 17 2014
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Tue, 17 Jun 2014 22:58:24 -0700
"H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> wrote:

 On Wed, Jun 18, 2014 at 05:40:47AM +0000, Sebastian Unger via
 Digitalmars-d wrote:
 But it is possibly an acceptable hack around a shortcoming in the
 language.
 Comming from C++, it's not as though I'm not used to those.
 Just a shame to have to resort to it when D is so pretty close to
 getting rid of dirty hacks more or less completely.
[...] I don't see it as a hack, much less a dirty one. The language was designed precisely to allow implementing this kind of user-defined extensions easily. In fact, there has been a recent trend to move things *out* of the core language where a library implementation suffices.
It's certainly not a hack, and it's a good example of how we can do quite a bit with the language without having to actually add to the language, but I think that most of us agree that Rebindable is an undesirable solution, and we'd welcome it if it could be done cleanly in the language. The problem is that doing it in the language has proven to be incredibly difficult due to how the compiler was written. Head-constness is something that's requested a _lot_ less frequently though (in fact, I think that this is the first time that I've seen it brought up), so if head-constness were the only issue, I don't think that many of us would be all that annoyed at the fact that we couldn't do it in the language itself. - Jonathan M Davis
Jun 17 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Head-constness is something that's requested a _lot_ less 
 frequently
 though (in fact, I think that this is the first time that I've 
 seen
 it brought up), so if head-constness were the only issue, I 
 don't
 think that many of us would be all that annoyed at the fact that
 we couldn't do it in the language itself.
Often I have functions that take an array as argument, like this foo: void foo(int[] arr) {} void main() {} In many cases I'd like to modify the array contents, but I'd like a way to tell the D type system that inside foo I don't want to change the length of the array arr, nor that I want to rebind the pointer. This is head-const and it's not useful to avoid bugs outside foo (because length and ptr of arr are values, so foo can't change their value at the calling point), it's useful to me to avoid modifying the array length by mistake inside foo: void foo(int(const[]) arr) {} void main() {} So I'd like to use for array Head-constness. An advantage of this kind of constness is that it doesn't change the type system a lot, because the constness of the length+ptr of arr is not visible outside foo. Bye, bearophile
Jun 18 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
 the constness of the length+ptr of arr is not visible outside 
 foo.
So the mangling of the function foo could be the same as before. Bye, bearophile
Jun 18 2014
prev sibling next sibling parent "w0rp" <devw0rp gmail.com> writes:
On Wednesday, 18 June 2014 at 05:40:48 UTC, Sebastian Unger wrote:
 On Wednesday, 18 June 2014 at 04:38:25 UTC, Meta wrote:
 On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger 
 wrote:
 There's no head const in D, but you can emulate it. This is a 
 *very* basic example that you can expand upon.

 http://dpaste.dzfl.pl/55cb22153fcc
Thanks for that link. Yes, that is close. I'd even feel reasonaly well about it if it was in phobos so everybody can use the mechanism consistently. It does not however, quite meet the mark of "with ease". But it is possibly an acceptable hack around a shortcoming in the language. Comming from C++, it's not as though I'm not used to those. Just a shame to have to resort to it when D is so pretty close to getting rid of dirty hacks more or less completely. Cheers, Seb
I wish people would not call library solutions to problems "dirty hacks." I often think the opposite. Changes in syntax can be hacks because a language doesn't allow you to define the semantics yourself.
Jun 18 2014
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 18 Jun 2014 01:40:47 -0400, Sebastian Unger  
<sebunger44.remove gmail.com> wrote:

 On Wednesday, 18 June 2014 at 04:38:25 UTC, Meta wrote:
 On Wednesday, 18 June 2014 at 01:31:33 UTC, Sebastian Unger wrote:
 There's no head const in D, but you can emulate it. This is a *very*  
 basic example that you can expand upon.

 http://dpaste.dzfl.pl/55cb22153fcc
Thanks for that link. Yes, that is close. I'd even feel reasonaly well about it if it was in phobos so everybody can use the mechanism consistently. It does not however, quite meet the mark of "with ease". But it is possibly an acceptable hack around a shortcoming in the language. Comming from C++, it's not as though I'm not used to those. Just a shame to have to resort to it when D is so pretty close to getting rid of dirty hacks more or less completely.
It's not a dirty hack, it gives you exactly the control you desire. D has extremely powerful mechanisms to make things that look like builtin constructs, but are really library types. The given mechanism should optimize down to direct assignments and reads via inlining. I agree it should be in phobos. It just needs a template constraint to make a non-reference type into a reference type, and it would be good to go into std.typecons. -Steve
Jun 19 2014
prev sibling next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Sebastian Unger"  wrote in message 
news:ebzakjopnllweizsikai forum.dlang.org...

 I have two classes A and B. Each object of class A is associated
 with a particular object of class B. This association is not
 supposed to change throughout the lifetime of the object of A.
I think D used to have this in the form of the 'final' storage class for variables. I'm not sure why we got rid of it.
Jun 17 2014
parent Jacob Carlborg <doob me.com> writes:
On 2014-06-18 08:35, Daniel Murphy wrote:

 I think D used to have this in the form of the 'final' storage class for
 variables.  I'm not sure why we got rid of it.
If I recall correctly it was also how "const" worked in D1. -- /Jacob Carlborg
Jun 19 2014
prev sibling parent reply "Chris Nicholson-Sauls" <ibisbasenji gmail.com> writes:
Ok, I must be missing something...

Just to make sure I'm understanding the OP: he wants to create 
two classes, A and B, such that each instance of A must be given 
a B to cling to, and which cannot be reassigned?  In what way is 
the following insufficient?


class B {/*...*/}

class A
{
     this(B someB)
     {
         _b = someB;
     }

     invariant
     {
         assert(someB !is null);
     }

     private B _b;

      property B b() const
     {
         return _b;
     }
}


Or is it that he wants to prevent even the code in method bodies 
or same-module functions from reassigning it?  In that case, I 
see two basic things to do:

  1) Isolate A (and B if it makes sense) into a module all by its 
lonesome
  2) Don't write `_b = ...`



Am I missing something, or is it really that simple?  (Not that a 
guaranteed non-rebindable type wouldn't be a nice thing to have, 
mind you.)
Jun 19 2014
parent "Chris Nicholson-Sauls" <ibisbasenji gmail.com> writes:
On Thursday, 19 June 2014 at 08:50:55 UTC, Chris Nicholson-Sauls
wrote:
     invariant
     {
         assert(someB !is null);
     }
Obviously that should be assert(_b !is null)...... I need more caffeine before posting.
Jun 19 2014