On Tue, 28 Jul 2009 12:30:00 -0400, Andrei Alexandrescu
<seewebsiteforem...@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