properties

Steven Schveighoffer schveiguy at yahoo.com
Tue Jul 28 10:20:30 PDT 2009


On Tue, 28 Jul 2009 12:30:00 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> Steven Schveighoffer wrote:
>>  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.

Yes, I agree.  But there is also a subtle problem we can solve at the same  
time.  You keep missing the point.

Let me come at another angle.  You can't view properties as some sort of  
enforcement by the compiler.  The compiler is not guaranteeing that if you  
call something without parentheses, it doesn't execute arbitrary code, it  
has nothing to do with what the compiler guarantees.  But the *meaning*  
that the author of the function wishes to convey is available via the  
requirement of parentheses or lack thereof.  The author of the code is  
saying "I wrote this function as if it were a field."

It's the same thing as function names.  The compiler allows you to name  
your functions how you wish, and enforces that foo is different than bar.   
Why is this important?  Because foo does something different than bar.   
And to a user, that's obvious, because in english foo means something  
different than bar.  What if the compiler allowed you to call functions as  
long as what you typed was an unambiguous prefix of the function name.   
For example:

struct S
{
    int foo();
    int flu();
    int bar();
}

This is valid code:

S s;
s.fl();
s.b();
// s.f(); // doesn't compile because its not unambiguous

Why is this advantageous?  Well, it saves you from having to type the  
whole function name.  It's unambiguous, so there is no problems as far as  
the compiler is concerned, so its easily implemented.  But why don't we  
have a wonderful time-saving feature like this?  Because it would be a  
nightmare to read.  You can change the implied english meaning of the  
function by just using its prefix.  But the compiler doesn't care, because  
it has no idea what the english meaning of the words are, and it's  
satisfied that you made an unambiguous decision.

Back to our problem at hand, by allowing one to call functions with or  
without parentheses you are not only changing the implied meaning of the  
function, but you have removed the ability of the author to convey that  
meaning with simply the requirement of parentheses.  He has to explain  
"this is a property" through by making the function name reflect that  
fact, or be an ass and say "well you shouldn't assume things based on  
parentheses, look it up dummy!"

Yes, if we solve the problem of setters, we have killed a huge wart on D,  
but why ignore the other warts?

>>> 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.

Just like D!

struct S
{
   const int readonlyfield;
   int readonlyproperty();
}

Yes, that's right.  readonly is analogous to const.

>>> 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!

I explained this above.  I'll reiterate: The enforcement of "field-like"  
by the compiler is not the point of properties, the ability given to the  
author to document that fact is the point.

>
>> 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?

It's less verbose, makes the code read better, allows you to avoid using  
functions to do everything.  As another example, Java doesn't have  
operator overloading, so BigInteger is horrific to use, calling functions  
for each operation.  So would you argue that C# or D with operator  
overloading isn't better because operators are just functions, why call  
them something else?

>> 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.

No.  The interface benefits are explained above.

>>> 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.

I want to use the parentheses or lack thereof as part of the human meaning  
for the function/property.  Making them optional means I can't do that.

>
>> 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.

I would be pleased, how can it be solved?

>> 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.

But my way is orthogonal to writing normal functions.  Your rule  
mistakenly identifies normal functions as properties.

>
>> 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.

Yes, and it is well established that opXxx shouldn't be used for arbitrary  
function names.  But you are expanding that rule to basically any function  
name, which means all functions are subject to being misinterpreted by the  
compiler, no matter what you name them.

>> 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.

It's a sacrifice in the name of clarity.

>>>> 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.

I can live without overloading setters, I don't think it's a requirement,  
but it would be possible with my method.  That's the only point I was  
trying to make.

-Steve



More information about the Digitalmars-d mailing list