Possible @property compromise

Zach the Mystic reachBUTMINUSTHISzach at gOOGLYmail.com
Thu Jan 31 16:59:46 PST 2013


On Thursday, 31 January 2013 at 22:54:21 UTC, Steven 
Schveighoffer wrote:
> C# has properties like this:
>
> property int foo {
>   get {return _foo;}
>   set {_foo = value;}
> }
>
> Your proposal looks like this:
>
> foo struct {
>    int opGet() {return _foo;}
>    void opSet(int value) {_foo = value;}
> }
>
> What I see is that the getter and setter are assigned specific 
> contextual keywords (opGet vs. get, and opSet vs. set). It 
> seems like a very similar (albeit more verbose) solution.
>
> What I had originally suggested for properties is this:
>
> property int foo {
>    int get() {return _foo;} // only one getter allowed
>    void set(int v) {_foo = v;}
>    void set(float v) {_foo = (int)v;} // more than one setter 
> allowed
> }
>
> I think these are all along the same line of solutions.  I 
> don't think they are bad, but clearly they weren't used 4 years 
> ago, so it may be difficult to convince Walter to use them now.
>
>> My opGet is just another opXXX definable for all structs, not 
>> just properties.
>
> I didn't see that, but I also don't really see the point of 
> that.  What value does opGet have unless it's a getter for a 
> property?
>
>> I had said it was necessary to achieve structs as properties, 
>> but I think I was wrong. It's just the equivalent of:
>>
>> int __someRandomFunction() { return _propValue; }
>> alias __someRandomFunction this;
>>
>> But it would be syntactically nicer, much like Highlander 
>> structs are syntactically nicer. Therefore, the only language 
>> change absolutely required would be making non-static structs 
>> nested in structs behave like non-static structs nested in 
>> functions, which they arguably should do anyway. Also under 
>> the hood, some important optimizations getting rid of pointers 
>> for data-less structs.
>
> This is a VERY bad idea.  A struct is POD.  For example, 
> consider a range type for a container.  You may not NEED to 
> have a pointer to the container, so that is wasted bytes.
>
> Also note that structs are not meant to have internal pointers.
>  So a "property" struct with an internal pointer
>
> The strange case for a struct type inside a function kind of 
> makes sense, because of the ability to access the function's 
> variables, and because you can't really move the stack frame.
>
> -Steve

I think my suggestion goes far beyond what you suspect. It goes 
way beyond mere getting and setting of variables. Here is 
basically how you implement a basic int as a property, assuming 
my new syntax and language adjustments. You need: 1) a struct to 
have the property in, which is just a normal struct. 2) An actual 
integer which will be indirectly accessed by using the 
properties. Let's call it "_n" and the property "n". 3) a struct 
to hold all of the property functions which access _n. THIS 
STRUCT CONTAINS NO DATA OF ITS OWN. 4) A bunch of methods 
implementing all the operators you want. For int, that's quite a 
lot, so I'll shorten it to a getter, a setter, and an adder. I'll 
even leave out opGet and use an alias to what might as well be 
opGet. I'll give the adder a little personality because what's 
the point of properties if they don't do something different from 
a basic type?

struct myStruct
{
   int _n;
   n struct
   {
     int __mightAsWellBeOpGet() { return _n; }
     alias __mightAsWellBeOpGet this;

     int opAssign(int newN) { _n = newN; return _n; }
     int opBinary(string op) (int rhs)
     {
       static if (op == "+")
       {
         writeln("You sure are adding a funky int, my friend...");
         return _n + rhs;
       }
       else static assert(0, "Operator "~op~" not implemented");
     }
   }
}

This is not some kind of special property implementation. n is a 
struct. It has no data and therefore is a very peculiar kind of 
struct. A struct with no data needs only one instance, ever. 
Copying it is pointless. Taking its address is pointless. 
Creating a new instance is pointless. Passing it by ref is 
pointless. All operations which require more than one instance 
are pointless, which is why it doesn't need a separately defined 
type. The type and the instance can therefore use the same name, 
n in this case.

Note that n uses the new rule which allows it access to its 
parent's scope, the same way it would in a nested function. The 
only pointer it needs is the same pointer used for myStruct, 
since myStruct actually stores some data.

Using the int is as simple as:
myStruct foo;
foo.n = 4; // Calls opAssign
writeln(foo.n); // uses alias this to call __mightAsWellBeOpGet
writeln(foo.n + 4); // Calls opBinary. Prints:

You sure are adding a funky int, my friend...
8

There's literally nothing these properties can't do that a 
full-fledged struct type couldn't do.


More information about the Digitalmars-d mailing list