properties

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Tue Jul 28 09:30:00 PDT 2009


Steven Schveighoffer wrote:
> On Tue, 28 Jul 2009 11:11:09 -0400, Andrei Alexandrescu 
> <SeeWebsiteForEmail at erdani.org> wrote:
> 
>> Steven Schveighoffer wrote:
>>> On Tue, 28 Jul 2009 10:16:16 -0400, Andrei Alexandrescu 
>>> <SeeWebsiteForEmail at erdani.org> wrote:
>>>
>>>> I think inferring meaning from the presence or absence of "()" is 
>>>> rather dicey.
>>>  Really?  Then why name your functions things like empty, why not 
>>> ex245, to make them look it up, making *sure* they know what the 
>>> meaning is before they use it.
>>
>> I didn't say not to infer meaning from the name.
> 
> No, you're saying inferring meaning from parentheses is not a good 
> idea.  I think it's the same thing as saying that inferring the meaning 
> from a function/field name is not a good idea (just in a more sarcastic 
> way...).  When you see parentheses, you infer function.  When you don't 
> you infer field/property.  Note that I'm not just pulling this out of a 
> hat, it's the way people already think, you should acknowledge that.

I acknowledge that in C, C++, and Java, you must add () to call an 
argument-less function. I also acknowledge that in C# a.b could mean 
either a field access or execution of arbitrary code.

>>> As one other person stated, they thought empty() emptied a range.
>>
>> Well it doesn't.
> 
> Exactly, so why do you think he thought that?  Let's take someone who's 
> used a language that uses () do denote a function, and no parens to 
> denote a field (there are a few of them out there).  Would that person 
> ever think that
> 
> x.empty;
> 
> means "empty the contents of x"?  The answer is no, not ever.  Whether 
> you like it or not or think it's dicey or not PEOPLE WILL INFER MEANING 
> FROM PARENTHESES.  I even do it, even though I *know* that it's dicey.  
> I hate having to look up usages of things that make no sense because I 
> have no idea what the code is doing.  It's so much better when the 
> meaning is clear from the code itself.

I acknowledge that some people infer meaning from parentheses. I mean, 
there's at least one :o).

>>> Being able to read code and understand what it means without 
>>> resorting to documentation is the sign of a good choice of symbol names.
>>
>> Sure.
>>
>>> The presence or absence of parens is a hard-coded accepted meaning of 
>>> field vs. function.
>>
>> I understand how some people want to derive meaning from obj.foo() 
>> versus obj.foo. I think they shouldn't in D. I mean D has had for 
>> years the behavior that you could drop the trailing empty parentheses.
> 
> And for years, there have been complaints about it.  This will 
> continuously be a thorn in the side of D adoption until it is resolved.

Again, most complaints have been directed towards writeln = 5. I think 
that's the major problem to be resolved.

>>> Properties build on this notion by making a virtual field that 
>>> actually resolves to a function (but behaves like a field, and this 
>>> is an important accepted meaning).
>>
>> Not quite. C# has allocated a language feature for properties. Yet 
>> they allow you to write write-only properties, which do NOT behave at 
>> all like fields
> 
> I'll give you that one, but that's an uncommon "because we can" case.

I acknowledge that you give me that one.

>> and also read-only properties, which also don't behave like fields.
> 
> Ever heard of readonly fields?  Yes, they exist in C#.  Besides, that's 
> one of the benefits of properties, you can do things that you can't do 
> with fields, otherwise why have them?

So now C# has two ways of providing a readonly field. Doesn't quite look 
like an example to follow.

>> Guess what - they both behave like functions. So their properties are 
>> an elaborate mechanism that is actually thoroughly unchecked, thus 
>> going back to what you could do by calling functions. So why the hell 
>> did they define the feature in the first place? Oh, for allowing 
>> people to write a.foo() instead of a.foo. You know what, that's a bit 
>> disappointing for an entire language feature.
> 
> No, they did it to *force* you to write a.foo instead of a.foo(), to 
> make it more defined that foo is a field-like entity.

Which is not, because it can execute arbitrary code that is not 
restricted in any way. How good a design is that? Back to semantics by 
convention?

That's what I'm saying: if it could do anything, at least don't pretend 
it's anything special. It's a function!

> There's a subtle, 
> yet very important difference.  They saw the implementation of 
> properties in Java as a good thing, but Java relied on a social standard 
> that a method that begins with get is a getter, a method that begins 
> with set is a setter, and a method that begins with is is a boolean.  C# 
> provides a better way to convey that contract via properties.

Why is C#'s way better?

> D's implementation looks to me like a quick hack so D can say "look, we 
> have properties!"  They don't provide any of the interface benefits that 
> true properties do.

What are the interface benefits that "true" properties do? What is a 
"true" property? Something that could do anything. Surprise, that was 
already the charter of functions. Well thank you very much.

> Might as well go back to Java style, where you have 
> to name your properties getX, setX or isX.  But now, normal functions 
> are corrupted with the ability to use them as properties.

Yum.

>>>> Well I don't think so. To repeat what I wrote elsethread: foo = bar 
>>>> is rewritten into foo(bar) if and only if auto __x = foo, __x = bar 
>>>> works. This means, a setter only works if there's a corresponding 
>>>> getter. (Write-only properties be damned.)
>>>  This is a band-aid fix, easily broken.
>>>  int select(int timeoutMS = -1); // method on a socket, for example
>>>  Hell, even my TimeSpan problem would still fail.
>>
>> Well maybe you could change TimeSpan.
> 
> Lovely.  Force the developer to rename his functions because D is too 
> weak to allow defining a correct interface.

Or maybe because her use of name was too ambiguous.

> You didn't even address the 
> select example, I think that's a very compelling example of something 
> that breaks your rule.

I agree that that example reveals a problem. I also think that that 
problem could be solved, but I doubt that you'll be pleased.

> My point is that your rule only works if you write code in a certain 
> way,

Your rule also works if you write code in a certain way.

> and I don't think that should be a determination of whether 
> something is a property or not by the compiler, because the naming of 
> functions is supposed to be up to the developer, not the spec.

opXxx are up to the spec.

> It's 
> like a prejudice against certain coding styles without any good reason.

I don't see that. I more see a prejudice against dropping "()" when 
calling a function.

>>> Also you are forgoing the ability to have overloaded setters, which 
>>> could be useful.  Not to mention getters for delegates.
>>
>> Wait, overloaded setters do NOT make the thing behave like a field, 
>> but you were stating how nice that is a few paragraphs ago! So what is 
>> it that you think is good?
> 
> Yes they do.  It makes them behave like a variant field.

Then write a function that takes a variant instead of overloading.

> e.g.
> 
> x.timeout = 5.5; // set timeout to 5.5 seconds
> x.timeout = TimeSpan.seconds(5); // set timeout to 5 seconds exactly
> 
> And what about getters for delegates?  That problem is still unresolved 
> by your rule.

I believe it's a minor problem that does not impede people from getting 
work done.


Andrei



More information about the Digitalmars-d mailing list