On Mon, 28 Jan 2013 08:20:23 -0500, Andrei Alexandrescu <[email protected]> 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

Reply via email to