February 01, 2013
On Friday, 1 February 2013 at 18:34:01 UTC, Steven Schveighoffer wrote:
> I think you are wrong in how you assume a struct works, but not in your attempt to implement properties.  Struct is just not a key to this formula.

I disagree. It is absolutely the fundamental key to this formula.

> Note that many (including myself) consider the overloading of static to be a *detriment*.

I guess there's certainly a matter of taste involved here. Had you suggested another keyword, or what had your preferred suggested syntax looked like?

> You are applying struct where none is needed.
>
> The current front accomplishes what you have shown except it does not require an actual struct instance (as your code does), and it's far easier to understand and implement than your method.
>
> What you are trying to do is establish a *namespace* in which to declare operator overloads.  The whole idea that it has to be a struct is incorrect, it does not need a "struct" wrapper.
>
> I think you are not understanding how a struct is implemented, and how it's methods are implemented.  A struct function without a 'this' reference is a static struct function.  Nothing different from a standard function, except it is in the struct *namespace*.  I think this is what you really are after, a separate *namespace*.
>
> I think *that* idea has merit, and should be examined.  Drop the struct, and you are back to the table.
>
> -Steve

I'm sorry we couldn't find common ground here. I can imagine two camps developing, one with your ideas and one with mine. As far as a static struct function, how could it get the pointer to its enclosing struct, which it needs in order operate on the enclosing struct's data?
February 01, 2013
On Fri, 01 Feb 2013 14:17:00 -0500, Zach the Mystic <reachBUTMINUSTHISzach@googlymail.com> wrote:

> On Friday, 1 February 2013 at 18:34:01 UTC, Steven Schveighoffer wrote:
>> I think you are wrong in how you assume a struct works, but not in your attempt to implement properties.  Struct is just not a key to this formula.
>
> I disagree. It is absolutely the fundamental key to this formula.

Well, we can disagree, but you still haven't explained why it's fundamental.  Other languages have implemented properties just fine without having to specify that they are structs or aggregate types.  Until you come up with a compelling reason for structs, I'll stand by my position.

>> Note that many (including myself) consider the overloading of static to be a *detriment*.
>
> I guess there's certainly a matter of taste involved here. Had you suggested another keyword, or what had your preferred suggested syntax looked like?

@property.  It's already there, already used for properties.

@property foo {

   int get(); // or opGet
   void set(int val); // or opSet

   opBinary(...)  // etc.
}

> I'm sorry we couldn't find common ground here. I can imagine two camps developing, one with your ideas and one with mine. As far as a static struct function, how could it get the pointer to its enclosing struct, which it needs in order operate on the enclosing struct's data?

There is NO difference between a static struct function and a normal module-level function, EXCEPT in the namespace.  How could it get the pointer to its enclosing struct?  It can't.  Because a struct TYPE doesn't HAVE an enclosing struct.  It could have an enclosing struct TYPE, but that's it.  In order to have an instance pointer, it needs to have an instance, and you need to have a non-static struct function.

Now, you are proposing that we have these special structs (nested structs) must be labeled static, but are not actually static (their methods require a context pointer), who can never have any fields, and whose methods accept a this pointer is not the pointer to the struct instance, but the instance of the containing type (be it class or struct) they reside in.  To say this is "just another struct" is an extremely large stretch.

I don't want to come across as mean or condescending, but what you have described could never be considered a struct.  Period.  If you insist that struct is to be used, you will be bashing your head against a brick wall forever here.  Drop the idea that it must be a struct, and you may gain some traction.  I'm not saying this because it's my opinion, I'm saying this to prevent you from wasting any more time.

I don't really want to waste any more of my time either, if struct is what you insist on, then I will respectfully bow out of the conversation.

-Steve
February 01, 2013
On Friday, 1 February 2013 at 17:43:54 UTC, Zach the Mystic wrote:
[...]
>> Syntactically, we can allow the property to contain its own data internally, but the data will really belong to the hosted structure (class, struct, or module level).
>
> I don't like this because structs don't already work that way. All structs can work in exactly the same way. I'm pretty sure there's no need to treat these specially... except under the hood, where compiler optimizes away the unnecessary pointers in the case of data-free structs.

It's one thing to implement a struct, and another thing to implement nested structs that can refer to the host instance. I know some people want nested structs that can work in that way, but implementation is problematic because when the host struct is moved, then the nested struct has to move along with it and this one reason why we don't have them.

I am proposing that we avoid the nesting problem by storing all enclosed data outside in the host instance, but this means that the concept is more like a namespace than a real struct, i.e., it is not movable and cannot be accessed in isolation from the host.

>> Nothing really new needs to be implemented because there's no special need for storing a "this" pointer, and functions get called in the same way as before. The "this" is the host pointer. We can still refer to an inner and an outter this pointer, but that's really an alias for either the hosts "this" (outter) or the property namespace (inner), both use the same this pointer.
>
> The problem with overriding "this" is if you later add data to the struct, it will break any code that already uses "this". "outer" doesn't have this problem at all, and is arguably clearer. Therefore, I think "this" should simply be a compile-time error with a data-free struct.

The idea here is that we have a property implementation that behaves like a namespace but also has some of the features that structs have. We should not call this thing a struct because it is not a true struct, it's something else entirely, not a namespace and not a struct, but it shares some features with both.

If you add data to the namespace-struct, the data is not stored inside the namespace, it only appears that way, it's instead stored with the hosting object instance, be it struct, class, or module, so data storage is like a namespace.

The "inner" simply refers to the "this" pointer of the host instance, but limited to the data that was declared inside the namespace, the outter pointer refers to the "this" of the host instance as well, but limited to the hosts data instance only. For modules I don't think there's a this pointer, but that's an implementation detail that can be resolved.

>>
>> No, the struct-property will not behave exactly like a variable, and I think that idea is a dead end anyway because it's far too complicated to implement and has questionable value. I agree with Walter, it's needs to be put down so we can move on and come up with a better idea that can work and is really useful.
>
> I don't know, Rob T... Walter's recent article on half-floats shows that you can get a struct instance to look pretty darn close to a variable. Is there anything a variable can do that half-floats can't do? Because if not, we're in the money, dude. This does exactly the same thing, just with data stored outside the struct itself.

The Half-Float implementation is not a nested structure, and trying to implement nested structs is where all of the major difficulties come from.

>> I may intuitively feel this is a great idea, but we will need a few compelling  use cases that solve real world problems to make a case for it.
>>
>> --rt
>
> Yes, but on the other hand, if you provide all the functionality previously requested, plus a whole lot more, a compelling use case becomes a lot less important. Undiscovered country.

I think we can easily replace @property already with the namespace proposal, however it will not be the full variable emulation that some people had wanted.

I don't think full variable emulation can be done anyway and I've seen admissions that it cannot be done by some of the people who want to see full variable emulation. What we can get however is a much better implementation of the property concept through a new gadget that works like a namepsace with some of the nice features seen with structs. I doubt we'll ever see true nested structs that can reference data in a host structs instance and contain it's own data because it introduces a pointer sync problem when the structs are moved around.

At this stage in the discussion, I believe that Steven Schveighoffer is correct that we'll get more traction if we drop the nest struct idea and focus instead on implementing a D version of the C++ namespace, with the improvements that allows things like properties to be implemented.

If we can show that there are other uses for the idea, then it adds a lot more credibility to the idea because as it stands, we can get properties right now, but they suck (IMHO anyway). If the proposal is only a marginal improvement over what we have now, then it may not be seen as worth implementing.

--rt
February 01, 2013
On Friday, 1 February 2013 at 19:59:12 UTC, Steven Schveighoffer wrote:
> On Fri, 01 Feb 2013 14:17:00 -0500, Zach the Mystic <reachBUTMINUSTHISzach@googlymail.com> wrote:
>
>> On Friday, 1 February 2013 at 18:34:01 UTC, Steven Schveighoffer wrote:
>>> I think you are wrong in how you assume a struct works, but not in your attempt to implement properties.  Struct is just not a key to this formula.
>>
>> I disagree. It is absolutely the fundamental key to this formula.
>
> Well, we can disagree, but you still haven't explained why it's fundamental.  Other languages have implemented properties just fine without having to specify that they are structs or aggregate types.  Until you come up with a compelling reason for structs, I'll stand by my position.

Okay, fair.

>
>>> Note that many (including myself) consider the overloading of static to be a *detriment*.
>>
>> I guess there's certainly a matter of taste involved here. Had you suggested another keyword, or what had your preferred suggested syntax looked like?
>
> @property.  It's already there, already used for properties.
>
> @property foo {
>
>    int get(); // or opGet
>    void set(int val); // or opSet
>
>    opBinary(...)  // etc.
> }

I'm totally sorry. I had meant that some time ago, static was not used so widely in D, and I'll concede it's a bit bulky, for what it does. I wondered what you wanted then that would look or feel better than having "static" plastered all over the place.

Having said that, I admit your syntax for @property is pretty good. I think it does the job. Now I have to demonstrate why structs would do the job better.

> There is NO difference between a static struct function and a normal module-level function, EXCEPT in the namespace.  How could it get the pointer to its enclosing struct?  It can't.  Because a struct TYPE doesn't HAVE an enclosing struct.  It could have an enclosing struct TYPE, but that's it.  In order to have an instance pointer, it needs to have an instance, and you need to have a non-static struct function.
>
> Now, you are proposing that we have these special structs (nested structs) must be labeled static, but are not actually static (their methods require a context pointer), who can never have any fields, and whose methods accept a this pointer is not the pointer to the struct instance, but the instance of the containing type (be it class or struct) they reside in.  To say this is "just another struct" is an extremely large stretch.

Okay, I can see the confusion... what need to become static are all *current* nested structs. These new special structs are not labelled static at all, precisely because of how important it is for them to define functions which hold pointers to instances of their parent type, no different at all from how it currently works with structs nested in functions. It's a code breakage I'm talking about here. And thank goodness it's one that's relatively easily handled. All normal structs will now define functions which accept a hidden pointer to their enclosing scope. There will be a small performance penalty, just like when a struct inside a function is not marked static, for programmers who fail to mark their nested structs static when possible. My other posts here and a comment by Era Scarecrow on the other thread are starting to address how this transition might be mitigated:

http://forum.dlang.org/thread/kdukid$stg$1@digitalmars.com?page=13

> I don't want to come across as mean or condescending, but what you have described could never be considered a struct.  Period.
>  If you insist that struct is to be used, you will be bashing your head against a brick wall forever here.  Drop the idea that it must be a struct, and you may gain some traction.  I'm not saying this because it's my opinion, I'm saying this to prevent you from wasting any more time.
>
> I don't really want to waste any more of my time either, if struct is what you insist on, then I will respectfully bow out of the conversation.
>
> -Steve

Maybe we both need some time to think about what has already been said.
February 01, 2013
On 02/01/2013 08:59 PM, Steven Schveighoffer wrote:
> ...
> Note that many (including myself) consider the overloading of static to be a *detriment*.
> ...

The modifier actually has a consistent meaning.
Is it about overloading as in static if and static assert?

> ...
>
> Now, you are proposing that we have these special structs (nested
> structs) must be labeled static, but are not actually static (their
> methods require a context pointer), ...

This is not what static on an aggregate declaration means in D. A static struct is a struct that does not contain a context pointer as an implicit field. All member structs and aggregate members of structs are implicitly static.
February 02, 2013
On Friday, 1 February 2013 at 21:33:31 UTC, Rob T wrote:
> It's one thing to implement a struct, and another thing to implement nested structs that can refer to the host instance. I know some people want nested structs that can work in that way, but implementation is problematic because when the host struct is moved, then the nested struct has to move along with it and this one reason why we don't have them.

I am not proposing this and I don't think it's actually necessary. My nested struct is just a tried-and-true struct. So what's the difference? How does it still succeed? Not because it contains any special data or hidden pointers unto itself. Rather, because its *functions* are written to *accept hidden pointers*. That way they can operate on whatever instance of their parent's type gets sent to them. They could be optimized, in theory, to only accept pointers to instances they actually worked on. For example, if a nested member function did nothing but set an integer defined in a struct three nests up, it only need take an instance of that struct, but that's an advanced optimization, not necessary for a basic implementation which would simply pass three pointers to every three-deep nested struct member function. If you want an example, just ask.
February 02, 2013
On Saturday, 2 February 2013 at 03:14:30 UTC, Zach the Mystic wrote:
> On Friday, 1 February 2013 at 21:33:31 UTC, Rob T wrote:
>> It's one thing to implement a struct, and another thing to implement nested structs that can refer to the host instance. I know some people want nested structs that can work in that way, but implementation is problematic because when the host struct is moved, then the nested struct has to move along with it and this one reason why we don't have them.
>
> I am not proposing this and I don't think it's actually necessary. My nested struct is just a tried-and-true struct. So what's the difference? How does it still succeed? Not because it contains any special data or hidden pointers unto itself. Rather, because its *functions* are written to *accept hidden pointers*. That way they can operate on whatever instance of their parent's type gets sent to them. They could be optimized, in theory, to only accept pointers to instances they actually worked on. For example, if a nested member function did nothing but set an integer defined in a struct three nests up, it only need take an instance of that struct, but that's an advanced optimization, not necessary for a basic implementation which would simply pass three pointers to every three-deep nested struct member function. If you want an example, just ask.

I mean a code example. But since I'm already here:

struct A
{
  int _a = 1;
  B b;
  struct B
  {
    int _b = 1;
    C c;
    struct C
    {
      int_c = 1;
      int myMemberFunction() { return _a + _b + _c; }
    }
  }
}

How does myMemberFunction know about _a and _b? Because its implementation is actually:

int myMemberFunction(ref A __a, ref A.B __b, ref A.B.C __c) { return __a._a + __b._b + __c._c; }

I do find it frustrating that his kind of thing is necessary to get full compatibility between structs and properties, which would be so elegant.

Usage would be:

A a;
assert(a.b.c.myMemberFunction() == 3);

...which is secretly translated to this:

assert(A.B.C.myMemberFunction(a, a.b, a.b.c) == 3);
February 02, 2013
On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:
> assert(A.B.C.myMemberFunction(a, a.b, a.b.c) == 3);

That wouldn't compile, so you must mean:

assert(a.b.c.myMemberFunction(a, a.b, a.b.c) == 3);

What do you suppose would happen if I wrote the following?

struct A
{
  int _a = 1;
  B b;
  struct B
  {
    int _b = 1;
    C c;
    struct C
    {
      int _c = 1;
      int myMemberFunction() { return _a + _b + _c; }
    }
    static int otherFunction()
    {
      C cc;
      return cc.myMemberFunction();
    }
  }
}

void main()
{
  int i = A.B.otherFunction();
}
February 02, 2013
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);
}
February 02, 2013
On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:
> [..]

What I'm trying to tell you through those questions is that what you insists on calling a struct in your proposal is really just a template for a namespace that lives inside a struct or a class. And variables of those nested struct types are the actual namespaces.