On Sun, 11 Jan 2009 07:50:03 +0300, Andrei Alexandrescu
<[email protected]> wrote:
Miles wrote:
Daniel Keep wrote:
Yes, property syntax can simplify some cases, but this isn't one of
them.
One good distinction properties and normal functions ought to make is
that functions should never be called without (), and properties should
never have () unless it has a function type.
Current syntax allows crazy things like:
----------
exit = 1; // it is not an assignment
x = toString = getenv = "PATH"; // creepy, but valid D
if (fork == 1) // not comparing the value of a variable
----------
Walter and I see eye to eye that a possible solution would be to only
allow the a = b syntax as an alternative for a(b) only if there's also a
function a(). All of the above can be fixed within that framework.
It was criticized many times by different people as being a too complex and
obscure rule.
First, you allow to omit empty pair of braces. Now you understand that it was a
bad idea as it bring to many problems and ambiguities. But instead of /fixing/
the source of the issues, you are trying to /reduce/ number of those issues (by
narrowing range of cases where omitting parens allowed). That's a wrong way to
go. You can reduce them, but you can't eliminate them entirely this way.
It doesn't allow authors to define what is callable with property syntax and
what is not. For example, I know many people that never use default function
arguments because they cause too many problems with inheritance (some of them
come from languages that doesn't allow them at all). Instead, the define two
distinct functions:
class Foo
{
int bar(int i)
{
// do something more intelligent here
return i;
}
int bar()
{
// call main function with default arguments.
// Default arguments may be overridden in derived class.
return bar(42);
}
}
And a Pandora's Box is open:
Foo foo = new Foo();
foo.bar = -1;
One more case - properties can not return references:
class Foo
{
ref int bar()
{
return _bar;
}
private int _bar;
}
Foo foo = new Foo();
foo.bar = -1;
test.d(17): function test.Foo.bar () does not match parameter types (int)
test.d(17): Error: expected 0 arguments, not 1
Nevertheless, let's assume it is a bug and it will be fixed (one more case
where optional parens feature causes a compiler bug).
Then, what does the following code do:
class Foo
{
ref int bar()
{
return _bar;
}
void bar(int i)
{
_bar = i;
}
private int _bar;
}
Foo foo = new Foo();
foo.bar = -1; // which one of the functions is called? Both are suitable.
Compare it with the following one:
class Foo
{
void bar(int i = 0) {}
void bar() {}
}
Foo foo = new Foo();
foo.bar(); // which one is called?
DMC result for reference:
a.foo();
^
test.cpp(20) : Error: ambiguous reference to symbol
Had: A::foo()
and: A::foo(int )
Besides, it has nothing to do with issue below:
Also, currently, in D, if you have a property of a delegate type, you
will have a mess.
----------
int func2() { return 42; }
/* this is a property */
int function() prop() {
return &func2;
}
void main() {
auto x = prop; // ok, x is a func ptr
auto y = prop(); // unexpected: y is not int :-(
static assert (is(typeof(y) == int));
}
----------
With properties, you forbid the above syntaxes.
Well the above syntaxes could be forbidden other ways too.
Andrei
They should not be forbidden, they should be allowed!
Imagine a struct that emulates virtual behavior with methods as first-class
objects:
struct Message
{
string text;
void delegate() show() // property getter
{
return _showDg;
}
void show(void delegate(ref Message message) dg) // property setter
{
_showDg = () { dg(this); }
}
private void delegate() _showDg;
}
auto showDg1 = (ref Message msg) { writefln(msg.text); } // output to stdout
auto showDg2 = (ref Message msg) { MessageBox(0, "Message", msg.text, 0); } //
show a message box
Message message;
message.text = "Hello World";
message.show = showDg1;
message.show()(); // works but requires two pair of braces
message.show = showDg2;
message.show(); // this is a goal
How would you /allow/ that? Why don't you see that non-mandatory parens bring
more troubles than it /tries/ to solve.