Another Properties Proposal

Chad J gamerChad at _spamIsBad_gmail.com
Tue Aug 21 15:46:35 PDT 2007


OK how about this:

Type _foo;
Type getFoo() { return _foo; }
void setFoo(Type val) { _foo = val; }
property Type foo(getFoo,setFoo);
// or &getFoo and &setFoo if you prefer
// also for readonly and writeonly:
property Type foo(getFoo,void);
property Type foo(void,setFoo);

In this incantation, properties are a compile-time construct.
It just tells the compiler that we have something called "foo" which is
really a pair of functions, but we want it to behave exactly like a data 
field.

Also note the typing, this is to ensure that the property has a uniform 
type, since data fields don't have different types for when you read and 
write to them.  The getter and setter functions must have types that are 
the same as or implicitly convertible to/from the property's type.
Thus the following is correct:

int _foo;
short getFoo() { return cast(short)_foo; }
void setFoo(long val) { _foo = cast(int)val; }
property int foo(getFoo,setFoo);
// calling code might work like so
int bar = foo; // works, since int bar = getFoo(); works
foo = bar; // works, since setFoo( bar ); works

But if getFoo had been written this way:
float getFoo() { return cast(float)_foo; }
Then the compiler would give an error.

Another possible syntax (without new keywords, almost looks better too):
in Type foo(getFoo); // RO property
out Type foo(setFoo); // WO property
inout Type foo(getFoo,setFoo); // RW property

So far this is pretty much what Ender KaShae suggested in the original 
thread.

There is also the possibility to trap certain operations on the property:

inout Type foo(getFoo,setFoo)
{
   Type opPostInc()
   {
     scope temp = getFoo();
     temp += 4; // Different behavior
     setFoo( temp );
     return temp;
   }
}

thus opPostInc() would override the default language-defined opPostInc() 
for the property.

I'd also suggest that taking the address of a property returns a pointer 
to a delegate or function pointer to the setter.
Another thing that would be useful then is to allow the setter to 
(maybe) return a value.  That way the setter can act as a getter when in 
a pinch.
Now we can write template and generic code that take addresses of 
members and be mostly unaware of the difference between properties and 
data fields:

// baz is just some function. This is on the user's side of the prop.
T baz(T)(Bar arg)
{
   auto ptr = &arg.foo; // foo is a property, a data field works too
   T val = *ptr; // calls foo.setFoo(typeof(foo).init);
   return val;
}

Where "T val = *ptr;" expands to the following:
typeof(foo) delegate(typeof(off)) temp = *ptr;
T val = temp; // same as T val = temp(); by implicit properties.

- Not supplying a return type for the setter function would make taking 
the address of the given property into a compile-time error.
- The return type for the setter function would be under the same 
type-strictness scrutiny as the return type for the getter function.

Also note that the above use of delegates plays on the current property 
syntax.  Without implicit properties, the example would look like this:

T baz(T)(Bar arg)
{
   auto ptr = &arg.foo;
   T val = *ptr(typeof(foo).init); // fails if foo is a data field.
   return val;
}

If the setter of the property does not have a return value, it would be 
a compile time error to take the address of said property.  Should a 
user want to have the address operation return something else, like a 
pointer to the data underlying the property, then perhaps there should 
be an "opAddressOf" operator overload that is available only for 
properties.

Alternatively, we could just do what I found C# to do and make it a 
compile time error to take the address of a property.


Another issue might be whether or not to let properties override each 
other.  This is in the case of classes with inheritance.
Initially, I'd say no.  It is more likely that the getter and/or setter 
function(s) are what should be overridden.


Well I'm soaking up my time and I need to pack for D con, so I'll cut it 
short on describing what these beasts should expand to.  They should 
expand to whatever makes them behave as closely to data fields as 
possible from the property user's perspective.

- Chad



More information about the Digitalmars-d mailing list