Jump to page: 1 2
Thread overview
Using memberspaces for a property-like syntax and more
Feb 02, 2013
TommiT
Feb 02, 2013
Era Scarecrow
Feb 02, 2013
TommiT
Feb 02, 2013
Rob T
Feb 02, 2013
TommiT
Feb 02, 2013
TommiT
Feb 02, 2013
TommiT
Feb 02, 2013
TommiT
Feb 02, 2013
Rob T
Feb 02, 2013
Simen Kjaeraas
Feb 02, 2013
TommiT
Feb 02, 2013
TommiT
Feb 02, 2013
Jonathan M Davis
Feb 02, 2013
TommiT
Feb 02, 2013
TommiT
Feb 03, 2013
Era Scarecrow
Feb 03, 2013
TommiT
Feb 03, 2013
Rob T
February 02, 2013
I propose we just forget about the whole concept of a property, and instead add to D a new construct called 'memberspace'. Memberspace subdivides the 'space' in which the member functions and operators of a type live into separately named 'subspaces', like namespaces do for freestanding functions and classes in C++. Read more about the uses of this idea over there (it's not my idea):

http://accu.org/index.php/journals/1527

Here's how it could look like:

struct S
{
    int _value;

    memberspace space1
    {
        int opCall() const
        {
            return _value;
        }

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

        void method() const { }
    }

    memberspace space2
    {
        static int opCall()
        {
            return 123;
        }
    }
}

void main()
{
    S var;
    var.space1 = 42;
    assert(var.space1() == 42);
    assert(S.space2() == 123);
    var.space1.method();

    int n1 = var.space1; // error
    int n2 = S.space2;   // error
}

Now, imagine replacing the name of your memberspace with the name of the thing you used to call a 'property'.
February 02, 2013
On Saturday, 2 February 2013 at 09:14:30 UTC, TommiT wrote:
> I propose we just forget about the whole concept of a property, and instead add to D a new construct called 'memberspace'. Memberspace subdivides the 'space' in which the member functions and operators of a type live into separately named 'subspaces', like namespaces do for freestanding functions and classes in C++. Read more about the uses of this idea over there (it's not my idea):

 First impression: I don't know why but I don't like it.

 It feels like you're doing the following:

 1) Declare a struct and immediately instantiate it with the same name. (Or union, or similar)
 2) Only one declaration of this struct can exist, doesn't count as nested struct.
 3) Disable all constructors/postblit/opAssign except as follows

 The only thing it has really done is allow you to force the use of parenthesis during a call (but only the get, not the set). You're then defining all opBinary/opAssign methods that it works with which seems like it will end up bloating the code considerably but not giving back as much as it takes to write it.
February 02, 2013
On Saturday, 2 February 2013 at 13:03:49 UTC, Era Scarecrow wrote:
>  First impression: I don't know why but I don't like it.
>
>  It feels like you're doing the following:
>
>  1) Declare a struct and immediately instantiate it with the same name. (Or union, or similar)
>  2) Only one declaration of this struct can exist, doesn't count as nested struct.
>  3) Disable all constructors/postblit/opAssign except as follows
>
>  [..]

Memberspaces shouldn't feel like variables at all. They should feel exactly like C++ namespaces that live inside a struct or a class. You can't take the address of a namespace or pass it as an argument. It's just an identifier that can be used to separate two same names, like std::sort and boost::sort. A nice IDE also colors memberspaces differently from a variables, etc.

On Saturday, 2 February 2013 at 13:03:49 UTC, Era Scarecrow wrote:
>  [..]
>  The only thing it has really done is allow you to force the use of parenthesis during a call (but only the get, not the set).

I thought it was an unfortunate side-effect that my proposal doesn't give us the nice getter syntax:
int n = var.prop;
...but I'm glad you like it (if I understood correctly).

On Saturday, 2 February 2013 at 13:03:49 UTC, Era Scarecrow wrote:
> [..]
> You're then defining all opBinary/opAssign methods that it works with which seems like it will end up bloating the code considerably but not giving back as much as it takes to write it.

But luckily in D you can write a whole bunch of operators at once by writing a restricted template operator, like:

void opOpAssign(string op)(int rhs)
    if(op == "+" || op == "-" || op == "*"  || op == "/")
{
    mixin("_value" ~ op ~ "= rhs._value");
}

But you're right in that memberspaces require a more explicit declaration of a property than most other property implementations. But those property proposals where you only specify a getter and a setter, albeit faster to write, they all suffer from a possible performance issue when the type returned by getter is non-trivial to copy. I.e.
var.prop += 3;
...has to be done as:
var.prop = var.prop + 3

Also, those other property implementations don't enable you to call the methods of your property in an encapsulated manner. E.g. if you property has a non-const set_to_invalid method, you can't encapsulate further in the struct/class where the property is defined. I.e:
var.prop.set_to_invalid();
...calls directly PropType.set_to_invalid without the type of 'var' having anything to say about it. That's not good for encapsulation.
February 02, 2013
On Saturday, 2 February 2013 at 13:03:49 UTC, Era Scarecrow wrote:
>  First impression: I don't know why but I don't like it.
> [..]

Also, let's not miss the fact, that this proposal isn't really about properties anymore. It's about being able to divide your interface into multiple logical sections. It just so happens to be that this ability lends itself pretty nicely to implementing something that *looks* like a property.

There's nothing that says you should use opCall as the getter of your "property" like this:
var.prop()
...instead, it could use a method like:
var.prop.get()
...and you could even have multiple getters:
var.prop.get_regular()
var.prop.get_filtered()

I just thought that the use of opCall for 'properties' might be a good convention.
February 02, 2013
On 2013-14-02 10:02, TommiT <tommitissari@hotmail.com> wrote:

> I propose we just forget about the whole concept of a property, and instead add to D a new construct called 'memberspace'. Memberspace subdivides the 'space' in which the member functions and operators of a type live into separately named 'subspaces', like namespaces do for freestanding functions and classes in C++. Read more about the uses of this idea over there (it's not my idea):
>
> http://accu.org/index.php/journals/1527
>
> Here's how it could look like:
>
> struct S
> {
>      int _value;
>
>      memberspace space1
>      {
>          int opCall() const
>          {
>              return _value;
>          }
>
>          void opAssign(int v)
>          {
>              _value = v;
>          }
>
>          void method() const { }
>      }
>
>      memberspace space2
>      {
>          static int opCall()
>          {
>              return 123;
>          }
>      }
> }
>
> void main()
> {
>      S var;
>      var.space1 = 42;
>      assert(var.space1() == 42);
>      assert(S.space2() == 123);
>      var.space1.method();
>
>      int n1 = var.space1; // error
>      int n2 = S.space2;   // error
> }
>
> Now, imagine replacing the name of your memberspace with the name of the thing you used to call a 'property'.

This seems to be basically what I outlined in issue 5158[1].


[1] http://d.puremagic.com/issues/show_bug.cgi?id=5158

-- 
Simen
February 02, 2013
On Saturday, 2 February 2013 at 17:12:33 UTC, Simen Kjaeraas wrote:
> This seems to be basically what I outlined in issue 5158[1].
>
>
> [1] http://d.puremagic.com/issues/show_bug.cgi?id=5158

I don't understand your proposal. Are you saying you want the following code to compile?

void main()
{
    int a;
    void opAssign(int arg) {a = arg;} = 4;
}

And what would that code do? Also, how would you use your proposal to implement memberspaces?
February 02, 2013
On Saturday, 2 February 2013 at 18:37:11 UTC, TommiT wrote:
> On Saturday, 2 February 2013 at 17:12:33 UTC, Simen Kjaeraas wrote:
>> This seems to be basically what I outlined in issue 5158[1].
>>
>>
>> [1] http://d.puremagic.com/issues/show_bug.cgi?id=5158
>
> I don't understand your proposal. Are you saying you want the following code to compile?
>
> void main()
> {
>     int a;
>     void opAssign(int arg) {a = arg;} = 4;
> }
>
> And what would that code do? Also, how would you use your proposal to implement memberspaces?

I'm sorry, I mixed templates with template mixins. But I still don't understand your proposal, so if you could elaborate on it a bit more.
February 02, 2013
On Saturday, 2 February 2013 at 16:15:43 UTC, TommiT wrote:
> Also, let's not miss the fact, that this proposal isn't really about properties anymore. It's about being able to divide your interface into multiple logical sections. It just so happens to be that this ability lends itself pretty nicely to implementing something that *looks* like a property.
>

I agree. The previous property proposals suffer from being very specialized and not much of a useful extension to the language. We don't even need properties and one of the main goals, which is variable emulation is not even possible to implement so the best we'll get is partial emulation which prevents properties from being used as a drop in replacement for variables.

If we can emulate properties (with the limitations that properties must have), with a general extension such as namespaces, then we're far better off. If we can use the namespace concept and implement properties in Phobos, then it shows that the concept is really useful and generalized enough for implementing other solutions besides only properties.

--rt
February 02, 2013
On Saturday, 2 February 2013 at 15:56:41 UTC, TommiT wrote:
[..]
>
> Memberspaces shouldn't feel like variables at all. They should feel exactly like C++ namespaces that live inside a struct or a class. You can't take the address of a namespace or pass it as an argument. It's just an identifier that can be used to separate two same names, like std::sort and boost::sort. A nice IDE also colors memberspaces differently from a variables, etc.
>


Rather than feel exactly like C++ namespaces, I am wondering if we could define a memberspace as a type so that can be reused multiple times in various areas of an application. With templates, a memberspace can be transformed in various ways to work with different data types.

--rt
February 02, 2013
On Saturday, 2 February 2013 at 21:21:28 UTC, Rob T wrote:
> Rather than feel exactly like C++ namespaces, I am wondering if we could define a memberspace as a type so that can be reused multiple times in various areas of an application. With templates, a memberspace can be transformed in various ways to work with different data types.
>
> --rt

I think we can use template mixins to achieve that:

mixin template add_stuff(alias var)
{
    memberspace stuff
    {
        typeof(var) opCall() const
        {
            return var;
        }

        void opAssign(typeof(var) rhs)
        {
            var = rhs;
        }
    }
}

struct S
{
    int _value;

    mixin add_stuff!(_value);
}

void main()
{
    S s;
    s.stuff = 42;
    assert(s.stuff() == 42);
}
« First   ‹ Prev
1 2