February 02, 2013
On Saturday, 2 February 2013 at 06:04:01 UTC, TommiT wrote:
> What do you suppose would happen if I wrote the following?
>
> struct A
> {
 <snip>
>     static int otherFunction()
>     {
>       C cc;
>       return cc.myMemberFunction();
>     }

 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
February 02, 2013
On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:
> [..]

Then, if we used your proposed nested structs to implement properties, pretty weird things like this would become possible:

struct A
{
  int _value;

  struct B
  {
    int get() { return _value; }
    alias this = get;

    void opAssign(int v) { _value = v; }
  }

  B length;
}

void func(T)(ref A a, T oldLength)
{
  a.length = 100;
  // Trying to restore 'a' back to the old length:
  a.length = oldLength;
}

void main()
{
  A a;
  a.length = 5;
  func(a, a.length);
  assert(a.length == 100);
}
February 02, 2013
As proposal:

class Example
{
    public int IntProperty
    {
        get; private set;
    }

    private double _internalMember;

    double FloatProperty
    {
        get out { assert(result > 0); } body { return _internalMember * 42; }
        set in  { assert(value != 0); } body { _internalMember = value + 42; }
    }
}

Resulting code:

class Example
{
    private _autoGeneratedBackMember;

    public int get_IntProperty() { return _autoGeneratedBackMember; }
    private void set_IntProperty(int value) { _autoGeneratedBackMember = value; }

    public
    {
        double get_FloatProperty() out(result) { assert(result > 0); } body { return _internalMember * 42; }
        void   set_FloatPoperrty(double value) in { assert(value > 0); } body { _internalMember = value + 42; }
    }
}

1. Rid-of @property keyword, UFCS as they now. Optional parentheses for UFCS with one or two parameters, not for variable number of arguments.
2. General behaviour like C# properties. It's about getting address of property, ref property, property rewrite, virtual property, explicit get/set methods, property with value semantic, exlicit calling get/set methods etc.
3. Property can be exported to libray as "<out type> get_<Name>(), void set_<Name>(<in type>)".
4. Get property always have only out(result) { } contract.
5. Set property always have only in { } contract.

Thanks.

February 02, 2013
On Saturday, 2 February 2013 at 06:04:01 UTC, TommiT wrote:
> 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);

You're right. I don't know how the compiler stores the name of the function I meant underneath the hood. But it must such a mechanism for naming A.B.C.myMemberFunction, which is nothing  more than a function which takes a pointer, or in this case a few pointers, to instances of the appropriate classes. Non-static member functions generally must take pointers to instances of their types. The only difference between this:

struct A
{
  int _a;
  int getA() { return _a; }
}

And this:

struct A
{
  int _a;
}
int getA(ref A a) { return a._a; }

Is that the compiler does the work of including the hidden pointer automatically in the first case, and also encloses getA into a, I hesitate to say it too loud now... namespace, so that it can't just be reached from anywhere.

>
> 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();
> }

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.
February 02, 2013
On Saturday, 2 February 2013 at 17:25:57 UTC, Zach the Mystic wrote:
>> 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();
>> }
>
> 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.
February 02, 2013
On Saturday, 2 February 2013 at 07:10:00 UTC, TommiT wrote:
> On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:
>> [..]
>
> Then, if we used your proposed nested structs to implement properties, pretty weird things like this would become possible:
>
> struct A
> {
>   int _value;
>
>   struct B
>   {
>     int get() { return _value; }
>     alias this = get;
>
>     void opAssign(int v) { _value = v; }
>   }
>
>   B length;
> }
>
> void func(T)(ref A a, T oldLength)
> {
>   a.length = 100;
>   // Trying to restore 'a' back to the old length:
>   a.length = oldLength;
> }
>
> void main()
> {
>   A a;
>   a.length = 5;
>   func(a, a.length);
>   assert(a.length == 100);
> }

This code is both wrong and has nothing whatever to do with the current topic. Boiling down the template to its resulting function, and imagining _value as the intended entity:

void func(ref A a, int oldLength)
{
  a._value = 100;
  a._value = oldLength;
}
A a;
a._value = 5;
func(a, a._value);
assert(a._value == 5); // 5, not 100

func takes an int. It's not a reference, it's a copy.

Let's assume you meant void func(ref A a, ref int oldLength) {} instead. Well, if you pass a reference, set it, and then refer it, you're going to get the set value back. I'm sorry, you can't adjust a reference and then expect to get a phantom original copy back. While I may have made a mistake, I simply see no connection between this and the idea of properties as structs.
February 02, 2013
On Saturday, 2 February 2013 at 06:28:47 UTC, Era Scarecrow wrote:
>  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.

Does my suggested way of doing it not do this?
February 02, 2013
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. I don't think this will break much code, but I don't know.
February 02, 2013
On Saturday, 2 February 2013 at 06:28:47 UTC, Era Scarecrow wrote:
> On Saturday, 2 February 2013 at 06:04:01 UTC, TommiT wrote:
>> What do you suppose would happen if I wrote the following?
>>
>> struct A
>> {
>  <snip>
>>    static int otherFunction()
>>    {
>>      C cc;
>>      return cc.myMemberFunction();
>>    }
>
>  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.
February 02, 2013
On Saturday, 2 February 2013 at 17:49:44 UTC, Zach the Mystic wrote:
> On Saturday, 2 February 2013 at 07:10:00 UTC, TommiT wrote:
>> On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:
>>> [..]
>>
>> Then, if we used your proposed nested structs to implement properties, pretty weird things like this would become possible:
>>
>> struct A
>> {
>>  int _value;
>>
>>  struct B
>>  {
>>    int get() { return _value; }
>>    alias this = get;
>>
>>    void opAssign(int v) { _value = v; }
>>  }
>>
>>  B length;
>> }
>>
>> void func(T)(ref A a, T oldLength)
>> {
>>  a.length = 100;
>>  // Trying to restore 'a' back to the old length:
>>  a.length = oldLength;
>> }
>>
>> void main()
>> {
>>  A a;
>>  a.length = 5;
>>  func(a, a.length);
>>  assert(a.length == 100);
>> }
>
> This code is both wrong and has nothing whatever to do with the current topic. Boiling down the template to its resulting function, and imagining _value as the intended entity:
>
> void func(ref A a, int oldLength)
> {
>   a._value = 100;
>   a._value = oldLength;
> }
> A a;
> a._value = 5;
> func(a, a._value);
> assert(a._value == 5); // 5, not 100
>
> func takes an int. It's not a reference, it's a copy.
>
> Let's assume you meant void func(ref A a, ref int oldLength) {} instead. Well, if you pass a reference, set it, and then refer it, you're going to get the set value back. I'm sorry, you can't adjust a reference and then expect to get a phantom original copy back. While I may have made a mistake, I simply see no connection between this and the idea of properties as structs.

No, you're not getting it. The following is a function template:

void func(T)(ref A a, T oldLength) {...}

The type of parameter oldLength is going to be the type of the expression you pass as the second argument when you call func. If you call func like I did in my example:

A a;
func(a, a.length);

...the type of the second argument to func, a.length, is A.B, and therefore the specialization of func that ends up being called is:

void func(ref A a, A.B oldLength) {...}

...and variable a.length is being passed by value, not by reference.