On Mon, 27 Jul 2009 18:37:01 -0400, Andrei Alexandrescu <[email protected]> wrote:

Steven Schveighoffer wrote:
The "getter" notation that currently exists only has a few minor problems. The most major of those problems is if the return value is a callable type, such as a delegate, you can't easily perform the call on the returned value.

Thanks for a very lucid analysis!

You're welcome :)

Being that it isn't very bad for the getter property, would it make sense to leave that functionality? That is:
 1. A setter must be defined in the opSet_X(int x) form
2. A getter can be a function with no required arguments, but this getter should not return callable types

... with zero arguments.

No, callable types period.  Note that this does not compile:

class A
{
    int delegate(int foo) wyda()
    {
        return delegate int(int foo) { return foo;};
    }
}


int main(string[] args)
{
    auto a = new A;
    auto b = a.wyda(5); // line 14
    auto c = a.wyda()(5);
    return 1;
}

[ste...@steveslaptop files]$ dmd testme.d
testme.d(14): Error: function testme.A.wyda () does not match parameter types (int)
testme.d(14): Error: expected 0 arguments, not 1

commenting out line 14 compiles.


3. A getter can be defined in the opGet_X() form, and then using X() will be the eqivalent of opGet_X()(). There are small implications to leaving the existing getter syntax. Namely one can call a function not intended to be a getter in a property-like syntax, resulting in less-than-obvious code.

This I don't agree with. I am very happy that I define popFront() as a method and then call it without parens.

Knowing that you can call functions without parens, seeing code like:

r.popFront;

it's obvious that popFront is a function, not a property.

But, do you agree that this code looks less-than-obvious?

auto x = flush;

is flush a flag saying flushing should occur? is it a function that flushes something, and returns the success? I agree that the bizarre factor is not as bad as with setters, but it's still not as self-explanatory as if you know that something without parens must be a property for the compiler to accept it.

Also, without a dedicated property syntax for setters, you have the problem mentioned above with callable types. At the very least you need the alternate syntax, the automagic properties for zero-arg functions are optional.


Also, this distinction will be very hard to explain to newbies ("how come a getter is defined as x(), but a setter has to be opSet_x(...)?).

I don't see that as a problem. You just explain that the trailing () is not necessary, and then you tell them to define opSet_x if they want to enable obj.x = y.

Perhaps. I admit that I don't have any real evidence to support my claim, but I don't think you do either ;)


The more I look at it, the more I like the keyword solution. I do find the C#-like syntax which groups properties together appealing, but I think you only absolutely need that if you are going to have context-keywords, which I DON'T think we need. I do find the whole construct of C# properties tedious to type. With a keyword attribute, you could even group your properties together to save on typing/ugliness:
 property
{
   int x() {}
   void x(int n) {}
   bool empty() {}
}

Not a fan, but this would work. I just don't see why I need to go through with it.

Let's separate this problem into two sections:

1. do we have to hint to the compiler that a function is a property or not?

I think we do, otherwise, we have the strange setter anomalies, and the inability to return delegates from getters. If you think this is not the case, state your arguments and solutions to those problems. I don't think the compiler can tell if something is meant to be a property or not by looking at it.

2. Assuming #1 is true for either getters and/or setters, what should the hints be?

This is more of a bikeshed issue, but there are some technical issues to consider (- = negative, + = positive):

For an opSet style syntax (e.g. int opSet_foo()):
- There is a possible conflict between opSet_foo and foo. Since it would be the only operator function where the calling syntax is also valid symbol. i.e. opAddAssign is called via +=, which can't be a valid symbol. The compiler absolutely has to forbid this, which might be tough to implement. - The meaning is a bit cryptic, kind of like opApply. I understand that it follows in line with other operators, so you might realize it is special, but it's not obvious that something is a property (this is really a bikeshed issue). + Because the function is of a different form than the property call, you can use it as a function easily. For example, easy to get a delegate to it, just &opSet_foo. + no changes to parser! No new keywords (some people value this, but I'm not really one of them)

For a new keyword-style syntax (e.g. property int foo()):
+ Much easier for the compiler to resolve a conflict, since you are directly declaring the called symbol. + Easier to understand that foo is a property than with opSet_foo, and easier to know how to call it. - If you wanted to use the property as a function (for example, get a delegate to the property), it might be more difficult. For example, if a property is "property ref int foo()", &foo might give you the address of the returned value. I don't really know a great solution to this problem, maybe a cast? Maybe you forgo the ability to take the address of the return value, and just have it always be a delegate? - new keyword (some people might not like this, I don't really have a problem with it). + Easy to annotate groups of properties by enclosing them in an attribute block.

------

One more point. From my point of view, the readability of the code, and obvious meaning of the code to a user of the code is more important than the ease of development. I've always been a fan of verbose function names and variables which describe what the function/variable is rather than short easy to type names. For instance I loathe the module structure of phobos, simply because the module names are too terse. For me to try and find something, it's not obvious.

So to that point, I think it's more important to make the readability and self-explanatory nature of properties better than to make them easier to declare. Remember, you only define them once, but you use them over and over. Where is it better to save time, on reading the docs or on writing the declaration?

-Steve

Reply via email to