On Sunday, 3 February 2013 at 07:26:03 UTC, Zach the Mystic wrote:
On Sunday, 3 February 2013 at 03:34:23 UTC, Era Scarecrow wrote:
struct Dog {
int id;
struct Tail {
string colorOf = "Black"; //just data.
int getId() { return id; }
}
Tail tail;
void func(ref Dog rhs) {
//tail2 retains context pointer to rhs.
Tail tail2 = rhs.tail;
writeln(tail.getId()); //5
writeln(tail2.getId()); //10
}
}
There is a bug in this code and it would not compile. Your
getId must receive an instance of Dog. A tail by itself has no
dog. The compiler cannot rewrite tail.getId() to
someImaginaryDog.tail.getId(). It's easy to think about, once
you get used to it. Your getId accesses a variable defined only
in its parent struct. The compiler detects this and requires
receiving a hidden pointer to (and *only to!*) an instance of
the parent. The resulting top-level function is:
int getId(ref Dog __d) { return __d.id; }
See? It may only access a dog, but it's *defined* in the tail.
This is the exact behavior we're looking for, and it's easy to
implement and causes no real trouble, as far as I can see.
I don't see the bug. Tail is known to be a nested struct so it
is required to have it's context (parent) attached, so it
supplies it although silently; Therefore tail points to rhs &
rhs.tail. This is only valid as long as the reference to rhs
exists (or as long as this function exists for sure). Besides the
'id' think more it renamed to 'string dogName', therefore you can
tell which tail belongs to which dog, be it sparky or scruffy,
etc.
In this case the nested struct relies on information from it's
parent, but the parent doesn't need information from it's nested
structs, allowing it to be correct even if the tail gets changed
colors. This can have useful other effects in place like
compression, maybe DB management (a text query is replaced by a
compiled version of the same thing), etc.
Dog dog1 = Dog(5);
Dog dog2 = Dog(10); dog2.tail.colorOf = "White";
dog1.func(dog2);
//context pointer of d2 thrown away after copy,
//unless opAssign is declared and does something.
dog1.tail = dog2.tail;
assert(dog1.id == 5); //untouched
assert(dog1.tail.colorOf == "White");
At which case the tail if it's allowed to be copied should be
related but not strictly required to be updated or relied on
Dog for behavior.
Guess it takes a few rules and experiments to find the right
balance of accessibility vs reliability vs flexibility.
With the bug removed, will any of these issues pop up? My guess
is no.
Maybe... I forget what the issues were since I went to sleep.