On Fri, 01 Feb 2013 01:52:29 -0500, Zach the Mystic <[email protected]> wrote:

On Friday, 1 February 2013 at 04:33:05 UTC, Steven Schveighoffer wrote:
No, the struct must have data. If it doesn't, how does it get back to the owner type? In other words, your n struct must have a pointer to the myStruct instance it intends to modify _n on.

How does any function get hooked up with data? The compiler figures out what data is to be passed to which function. It's no different from how the compiler figures out how to pass data defined in one module to functions defined in a different module. Empty structs are just namespaces with powerful semantics. They have no pointers, unless they're nested in a struct with data, in which case they have the same pointer as any member function of that struct.

struct A
{
   int q = 23;
   void incrementQ() { ++q; }
}

How on earth could this function increment q when it's not even defined in the function?!?!? It must be a miracle. Oh, no wait, it needs a pointer to the struct in question. Duh.

No need to get snippy :)  Especially when you are wrong.

Try this:

struct A
{
   int q;
   struct B
   {
      void foo() {q++;}
   }
}

Won't compile. That's becuase foo is passed a reference to the A.B struct, not the A struct.

If you want it to compile, B will *necessarily* have to have a pointer to A.

If you want B's methods to be passed A's pointer, then this is not a struct. Plain and simple. It's just a namespace, the "just like any other struct" is meaningless, since it isn't.

Now, try this:

struct S {}

pragma(msg, sizeof(S).stringof); // outputs 1 (empty structs must have some size).

void foo()
{
  int q;
  struct A
  {
     void foo() {q++;}
  }

  pragma(msg, sizeof(A).stringof); // outputs 4 (or 8 on 64-bit machines)

}

Why? Because the reason those "miracle" nested structs work is because they have a hidden context pointer.

Even empty structs have size of 1 byte because they must have a 'this' pointer.


There's no difference with data-less structs inside regular structs.

struct A
{
   int q;
   incrementQ struct
   {
     void opCall() { ++q; }
   }
}

Where's the need for some hocus-pocus mystery pointer here? The empty struct has no data to worry about. Functions inside the empty struct get the same damn pointer as the other functions in struct A.

Then this is not a normal struct, in fact it has nothing to do with a struct.

But of course, you can't do this:

struct B
{
   int _q;
   q struct
   {
     int opUnary(string s)() if (s == "++")
     {
writeln("You know, I just wanted to have a conversation while I was busy incrementing q");
       ++_q;
writeln("I did all sorts of stuff with the increment operator while I was at it");
       return _q;
     }
   }
}

...with normal function calls.

Certainly you can:

struct B
{
   int _q;
   @property auto q()
   {
      static struct incrementer
     {
       int *_q;
       int opUnary(string s)() if (s == "++")
       {
writeln("You know, I just wanted to have a conversation while I was busy incrementing q");
         ++(*_q);
writeln("I did all sorts of stuff with the increment operator while I was at it");
         return *_q;
       }
     }
     return incrementer(&_q);
   }
}

Although, because of dumb rvalue/lvalue rules (apparently, incrementer is not an lvalue, so can't have ++ called on it), this doesn't actually compile...

Through some finagling, I can get this to compile, but it's not usable with this compiler bug:

import std.stdio;

struct B
{
    int _q;

    struct incrementer
    {
        int *_q;
        int opUnary(string s)() if (s == "++")
        {
writeln("You know, I just wanted to have a conversation while I was busy incrementing q");
            ++(*_q);
writeln("I did all sorts of stuff with the increment operator while I was at it");
            return *_q;
        }
    }

    private incrementer qinc; // needed to make incrementer an lvalue.

    @property ref incrementer q()
    {
        qinc._q = &_q;
        return qinc;
    }
}

void main()
{
    B b;
    assert(b._q == 0);
    ++b.q; // b.q++ doesn't work, another bug
    assert(b._q == 1);
}

But I think actually, if we are going to define get and set in C# style, it would be useful to be able to define all the operators. So that part of the plan has merit.

I think you need to drop the struct moniker. This is not a struct. You do that, and I think your proposal is on more solid ground.


Unless, of course, you pass the pointer to myStruct as the 'this' reference.

Ain't no "this" in an empty struct. Use "outer.this" instead.

outer is the pointer I am referring to. It's not magic, it must come from somewhere. If the struct has no this pointer, it's not a struct. A data-less struct *STILL* has a this pointer.


But then, this isn't a normal struct, and
I'm really failing to see why we have to make this a struct at all.

Because it's already implemented, except for a few details, because it opens up possibilities for properties other languages could only dream of, and because it obviates the need for tags like @property to provide far weaker functionality.

Hand waving doesn't solve the problems. The details are important to resolve.

What it seems like you have done is hijacked the 'struct' keyword for a property. It isn't a struct, and it doesn't obviate the need for a tag.

You say it's complicated, but I ask you this: does any other proposal completely eliminate the so-called eye-sore "@property" while also providing functionality with unknown potential which goes far beyond what people are used to? And the owner pointer problem is only a problem if we want to make the language complete and consistent with regard to normal non-static structs holding an outer struct pointer. I think having a use case for this type of struct would seal the deal, but as it is, I'm not sure.

What I mean by complicated is that it seems like a lot more work than it should be.

If we want to define new syntax to define properties, let's do it in a way that is concise and to the point. I don't want to make properties look like structs, they are not structs.

-Steve

Reply via email to