properties
Steven Schveighoffer
schveiguy at yahoo.com
Tue Jul 28 07:08:05 PDT 2009
On Mon, 27 Jul 2009 18:37:01 -0400, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> 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;
}
[steves at 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
More information about the Digitalmars-d
mailing list