Property discussion wrap-up

Steven Schveighoffer schveiguy at yahoo.com
Mon Jan 28 08:58:30 PST 2013


On Mon, 28 Jan 2013 08:20:23 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> One interesting fact is that we have evidence at hand. Optional parens  
> _exist_ today in D, and have for a while. The language has worked. They  
> haven't been a disaster.

I've seen some issues, but mostly for allowing normal functions as setters.

> Aside from discussions about @property itself, optional parens have just  
> worked. We also have evidence that UFCS is convenient and useful. People  
> use it and like it. And arguably UFCS and optional parens combine in a  
> lovely way.

optional parens are something that has been difficult to argue against.   
There is always the workaround of making your method names more verbose so  
they aren't mistaken for properties.

> We've also converted the Phobos codebase to work with the half-strong  
> -property switch. We've adorned a lot of functions with @property. I  
> don't see evidence of found bugs or improved code quality.  
> (Subjectively, I'd argue we actually degraded esthetics. There's no love  
> lost between me and that "@property" plastered everywhere.)

the improvement of @property is all in the eye of the code reader.  There  
are no "bugs" or code quality improvements, the improvements are for the  
sole benefit of reading the code, and defining the API.  If something is a  
@property, it should be accessed as a property.  Being able to enforce  
this results in cleaner and clearer code.

I've been doing mostly Objective C for the last 10 months.  Interestingly  
enough, objective C has a notion of @property that is quite similar to D.

You declare in the interface a property like:

@property(attributes) int value;

Where attributes can describe something about the property, is it atomic,  
is it reference counted, etc.

What does this mean?  It means there is a method for accessing value  
implicitly declared as:

-(int) value; // translates to int value(); in D

If attributes does not include "readonly", it also means there is a method  
for setting the value, implicitly declared as:

-(void) setValue:(int)val; // translates to void setValue(int val); in D

Now, note here that the @property declaration is COMPLETELY optional.  One  
can simply declare the two methods value and setValue:, and then Objective  
C allows the syntax:

int x = obj.value; // translates in objective C to [obj value];, a.k.a.  
obj.value(); in D
obj.value = x; // translates in objective C to [obj setValue:x];, a.k.a.  
obj.setValue(x); in D

note that dot syntax is reserved strictly for property access in Obj-C,  
field access is done via obj->field, and methods are done via [obj  
method].  So the comparison to D must take into account that D uses .  
notation for everything, making it a bit more confusing.

@property here serves two purposes.  Since properties are the ONLY way to  
publicly access class fields, it provides a very commonly-used boilerplate  
generation.  Second, with the given attributes, there is a corresponding  
@synthesize directive in the implementation that will create a default  
accessor and optional setter (assuming attributes does not include  
"readonly") that do the right thing, depending on whether the value is  
atomic, whether it needs it's reference count updated, etc.

But what is really interesting here is that like D's current  
implementation, the getter looks the same as a property or a method -- and  
this hasn't caused much confusion for the langauge.  However, UNLIKE D,  
the setter is unmistakable as a normal function when you use the method  
form!  [obj setValue:x] cannot be mistaken for something that doesn't set  
a field.

I would be perfectly fine ONLY defining @property on setters, and getters  
where the parentheses are confusing (i.e. getting a delegate/function  
pointer/functor).

I would be fine with D CANCELLING @property as long as we had something  
like Objective C, where the function form of a setter CANNOT be mistaken  
for a normal function.  In this case, we would have to live with delegate  
properties requiring two sets of parentheses.

But if you get rid of @property and we are back to D1-style properties,  
please acknowledge that the abuse of functions as setters is not a good  
situation.  I had "bugs" in prior D1 projects where a normal non-property  
function was easily misinterpreted as a property, and I ended up having to  
rename the function to something weird so it couldn't be mistaken as a  
property.  The nice thing about the objective-c solution is it puts the  
burden of naming convention on the *property* function.  With D1, the  
burden is on *all* functions to broadcast "no, I'm not a property".

>
> These are not "what if" hypotheses; they describe experience accumulated  
> from past events. Even people who dislike optional parens or UFCS must  
> agree that their sentiment is far from widespread - unlike, for example,  
> was the case for string lambdas.

These "past events" should be taken with a grain of salt, since @property  
was never fully realized.  In languages where properties were fully  
enforced, it has not caused problems or undue headaches.

-Steve


More information about the Digitalmars-d mailing list