February 02, 2013
On Saturday, 2 February 2013 at 17:33:38 UTC, TommiT wrote:
>> I was simply using A.B.C.myMemberFunction as a shorthand for whatever name the compiler uses underneath the hood to represent the non-static version of the function.
>
> Yes, I can see that now. I didn't understand that the code wasn't actual code but something that the compiler sees.
>
> But, you didn't answer my question. What would happen if I actually did write that code and click "compile". What would there be in the 'i' variable?
>
> Era Scarecrow already answered the question for you. The correct answer is that the code wouldn't compile. But I just want to see that you understand why it must be so.

I'm sure I'll get by, with a little help from my friends.
February 02, 2013
On Saturday, 2 February 2013 at 17:56:41 UTC, Zach the Mystic wrote:
> On Saturday, 2 February 2013 at 06:19:29 UTC, TommiT wrote:
>> On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:
>>> [..]
>>
>> What do you suppose would happen if I wrote the following?
>>
>> struct A
>> {
>>  struct B {}
>>
>>  B b1;
>>  B b2;
>> }
>>
>> void main()
>> {
>>  A a;
>>  assert(&a.b1 == &a.b2);
>> }
>
> With my new rules? It would be illegal to take the address of a struct which contained no data.

Yes, that is kind of what I was getting at with my question. But I'm going to ask the same thing in a better way now:

Given your new nested struct variable behaviour and my definition of struct 'A' quoted above, would the following lines compile?

static assert( A.B.sizeof == 0 );
static assert( A.sizeof == 0 );
February 02, 2013
On Saturday, 2 February 2013 at 18:03:32 UTC, Zach the Mystic wrote:
> On Saturday, 2 February 2013 at 06:28:47 UTC, Era Scarecrow
>> It would refuse to compile as a static function can't point to an instance/parent. I'm convinced you should not be able to return (or create an instance of) a nested struct outside of it's level of control or ability to reference properly.
>>
>> Had it not been static on the other hand...
>>
>>            int otherFunction()
>>
>> cc has the same level as c, so the return would be equal to: _a + _b + cc._c
>
> ... well, this function requires being called with instances of A, B, and C, so I believe it would error on that account. The only way to call this deeply nested thing would be with an instance of A, which makes sense, since it operates on a variable contained in A. It would have to look like:
>
> A a;
> int z = a.b.c.myMemberFunction();
>
> ... to work, I believe.

 Yes, it should be callable that way since it knows where a is at. However I would think a nested struct is more a implementation detail.

 This brings back training when I was on a database/web development. There were 4 tiers, the DB, the Query level (with all the queries), Logic level, then the GUI level.

 Now something in this was that each level would be separate and not know about the other. When you think about it, it makes sense since you can swap out one for another. But then I began to notice code that broke that very easily. The GUI level would be doing stuff like:

  //posted twice, once for html formatting
  <b>Price: $<?db.getPrices.query("select price from priceTable where x=x")?></b>

  <b>Price: $<?db.getPrices.query("select price from priceTable where x=x")?></b>

 Not a very large example, however it ended up that the gui was getting into specifics of variables and function calls in other levels that it shouldn't have known about.

 In short, nested structs would only be accessible (and passable) inside the struct that made it. Meaning that most likely the methods that work with it, and the struct itself should be private.
February 03, 2013
On Saturday, 2 February 2013 at 18:47:37 UTC, TommiT wrote:
> On Saturday, 2 February 2013 at 17:56:41 UTC, Zach the Mystic wrote:
>> On Saturday, 2 February 2013 at 06:19:29 UTC, TommiT wrote:
>>> On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:
>>>> [..]
>>>
>>> What do you suppose would happen if I wrote the following?
>>>
>>> struct A
>>> {
>>> struct B {}
>>>
>>> B b1;
>>> B b2;
>>> }
>>>
>>> void main()
>>> {
>>> A a;
>>> assert(&a.b1 == &a.b2);
>>> }
>>
>> With my new rules? It would be illegal to take the address of a struct which contained no data.
>
> Yes, that is kind of what I was getting at with my question. But I'm going to ask the same thing in a better way now:
>
> Given your new nested struct variable behaviour and my definition of struct 'A' quoted above, would the following lines compile?
>
> static assert( A.B.sizeof == 0 );
> static assert( A.sizeof == 0 );

Yes, I believe so. I don't see why not.
February 03, 2013
On Saturday, 2 February 2013 at 20:30:26 UTC, Era Scarecrow wrote:
> On Saturday, 2 February 2013 at 18:03:32 UTC, Zach the Mystic wrote:
>> On Saturday, 2 February 2013 at 06:28:47 UTC, Era Scarecrow
>>> It would refuse to compile as a static function can't point to an instance/parent. I'm convinced you should not be able to return (or create an instance of) a nested struct outside of it's level of control or ability to reference properly.
>>>
>>> Had it not been static on the other hand...
>>>
>>>           int otherFunction()
>>>
>>> cc has the same level as c, so the return would be equal to: _a + _b + cc._c
>>
>> ... well, this function requires being called with instances of A, B, and C, so I believe it would error on that account. The only way to call this deeply nested thing would be with an instance of A, which makes sense, since it operates on a variable contained in A. It would have to look like:
>>
>> A a;
>> int z = a.b.c.myMemberFunction();
>>
>> ... to work, I believe.
>
>  Yes, it should be callable that way since it knows where a is at. However I would think a nested struct is more a implementation detail.

I think this belittles just how important that implementation detail really is. Without a good design, the thing could be prohibitively difficult to implement.

>  This brings back training when I was on a database/web development. There were 4 tiers, the DB, the Query level (with all the queries), Logic level, then the GUI level.
>
>  Now something in this was that each level would be separate and not know about the other. When you think about it, it makes sense since you can swap out one for another. But then I began to notice code that broke that very easily. The GUI level would be doing stuff like:
>
>   //posted twice, once for html formatting
>   &lt;b&gt;Price: $&lt;?db.getPrices.query(&quot;select price from priceTable where x=x&quot;)?&gt;&lt;/b&gt;
>
>   <b>Price: $<?db.getPrices.query("select price from priceTable where x=x")?></b>
>
>  Not a very large example, however it ended up that the gui was getting into specifics of variables and function calls in other levels that it shouldn't have known about.

From what I understand generally, good encapsulation is a difficult design problem. I don't think you're alone.

>  In short, nested structs would only be accessible (and passable) inside the struct that made it. Meaning that most likely the methods that work with it, and the struct itself should be private.

Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.

You might as well use the built-in functionality for tagging whatever you want private or public, though. Consider this: software design doesn't end at language design. There's only so much a language can do to encourage good design before it starts to feel like it's strong-arming you into certain arbitrary ways of doing things. Doing this too much is actually *bad* language design.
February 03, 2013
On Sunday, 3 February 2013 at 02:55:44 UTC, Zach the Mystic wrote:
> Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.

If Tail is an autonomous struct/class, then it totally makes sense to put the definition of Tail outside of dog. This enables you to perhaps use the same Tail in Wolf's and Hyeena's definitions. If, on the other hand, Tail is not an autonomous type, but rather, needs to able to wag the dog, then Tail is really more like a separate logical section within Dog's definition, i.e. a namespace within Dog.
February 03, 2013
On Sunday, 3 February 2013 at 02:55:44 UTC, Zach the Mystic wrote:
> On Saturday, 2 February 2013 at 20:30:26 UTC, Era Scarecrow wrote:
>> Yes, it should be callable that way since it knows where a is at. However I would think a nested struct is more a implementation detail.
>
> I think this belittles just how important that implementation detail really is. Without a good design, the thing could be prohibitively difficult to implement.
>
> From what I understand generally, good encapsulation is a difficult design problem. I don't think you're alone.
>
>> In short, nested structs would only be accessible (and passable) inside the struct that made it. Meaning that most likely the methods that work with it, and the struct itself should be private.
>
> Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.

 Agreed 100%, Although a second (instance of) Dog may want to come about and them sniff tails. That's outside access, but it's still within the limits of the Dogs. In those cases a context pointer could be acceptable as long as it's ensuring the data exists (and can't return it from the function); But overwriting one instance with a different context pointer of another could have very curious side effects depending on design.

  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
    }
  }

  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 declared and does something.
  dog1.tail = dog2.tail;

  assert(d1.id == 5);   //untouched
  assert(d1.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.
February 03, 2013
On Thursday, 31 January 2013 at 14:48:15 UTC, Regan Heath wrote:
> On Thu, 31 Jan 2013 14:39:56 -0000, jerro <a@a.com> wrote:
>
>>> Now we're just name calling ;)  I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed.
>>
>> This is a really bad argument. The facts that language is being used by a large companies does not make it well designed. See PHP, for example - a *horrible* mess of a language, but it is being used at Facebook.
>
> Small point.  "using" != "standadized on".  The latter implies some evaluation and decision making was done prior to the choice, the former.. well..
>
>> (I don't have an opinion on objective C though, as I don't know the language)
>
> Neither.
>
> R

I bet the reason why Objective-C was chosen rather than C++ has more to do with licensing issues (LLVM wasn't rady at the time) and maybe GC than any other reason.
February 03, 2013
On Sunday, 3 February 2013 at 03:34:23 UTC, Era Scarecrow wrote:
>  Agreed 100%, Although a second (instance of) Dog may want to come about and them sniff tails. That's outside access, but it's still within the limits of the Dogs. In those cases a context pointer could be acceptable as long as it's ensuring the data exists (and can't return it from the function); But overwriting one instance with a different context pointer of another could have very curious side effects depending on design.
>
>   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.

>   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 declared and does something.
>   dog1.tail = dog2.tail;
>
>   assert(d1.id == 5);   //untouched
>   assert(d1.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.
February 03, 2013
On Sunday, 3 February 2013 at 03:15:57 UTC, TommiT wrote:
> On Sunday, 3 February 2013 at 02:55:44 UTC, Zach the Mystic wrote:
>> Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.
>
> If Tail is an autonomous struct/class, then it totally makes sense to put the definition of Tail outside of dog. This enables you to perhaps use the same Tail in Wolf's and Hyeena's definitions. If, on the other hand, Tail is not an autonomous type, but rather, needs to able to wag the dog, then Tail is really more like a separate logical section within Dog's definition, i.e. a namespace within Dog.

A dog's tail is not an autonomous struct/class. If you ever had a dog you would know that. Also, the dog's tail is no namespace because it contains tail-specific data too.