January 11, 2009
dsimcha wrote:
> I figure the vast majority of cases are going to be primitive types anyhow (mostly
> ints),

Yes, this is very true.

> and if someone defines operator overloads such that foo += 1 produces totally different observable behavior than foo = foo + 1, that's just too ridiculously bad a design to even take seriously.

Sure. It is bad coding style, it is ugly and the programmer who does this should be called for a meeting with his boss. But there are still ways to have sane behavior, even in such situations. See below.

> What do you think?  Is it worth
> ignoring a few hard cases in exchange for solving most cases simply and elegantly
> and without adding any new constructs?

Instead, I think it is more sane to use temporaries.

----------
	{
	  auto tmp = __get_foo();
	  tmp += 1;
	  __set_foo(foo);
	}
----------

It is the safest this way, principle of least surprise. If the caller does foo += 1, it will get that; if it does foo = foo + 1, it will still get that; if it does foo.call(), again, the behavior is still sane.

We must first attack the semantics. This have sane semantics. Then let the compiler optimize that as far as possible. The compiler inlines the getter and setter calls, then optimizes away the temporary, etc.
January 11, 2009
"bearophile" <bearophileHUGS@lycos.com> wrote in message news:gkd3b0$fkb$1@digitalmars.com...
> Miles:
>> In fact, if you follow the principle of orthogonality, instead of calling the function without parameters, it would be much more sensible to have 'foo' return the function address, and deprecate the address operator. Then you could have functions and function/delegate pointers with similar semantics (principle of least surprise).
>
> I agree.
>
>
>> But now it is quite already too late to fix this, unless we go through a long period of deprecating the current behavior, until we can implement the new sane one.
>
> Seeing how much experimental D2 is, I think there's time to fix design bugs still.
>

Even if it weren't for that, I would still consider this important enough to be worth the hassle of changing it. It would be better than letting D forever maintain the cruft of a particularly bad design decision (no offense, Walter) in the same way that C++ would.


January 11, 2009
"Nick Sabalausky" <a@a.a> wrote in message news:gkbuap$1khp$1@digitalmars.com...
> Objects (nouns) have attributes (nouns) and are capable of doing things (verbs).

That should probably be:

Objects (nouns) have attributes (adjectives/nouns) and are capable of doing things (verbs).

But, of course, adjectives (just like "direct/indirect objects") are themselves nouns.


January 11, 2009
Nick Sabalausky:
> Even if it weren't for that, I would still consider this important enough to be worth the hassle of changing it. It would be better than letting D forever maintain the cruft of a particularly bad design decision (no offense, Walter) in the same way that C++ would.

But I am not sure that proposed idea is the best, because in Python (that acts like that) you often enough write for mistake:

x = foo

Forgetting the (). In this case x gets a (kind of) reference to foo and not to its result. You can do something similar in that D proposal:

auto x = foo

So I think &foo and foo() are more explicit and better (better == less error-prone), to represent the pointer/delegate/closure, and to represent the calling.

Bye,
bearophile
January 11, 2009
"bearophile" <bearophileHUGS@lycos.com> wrote in message news:gkd53n$ikt$1@digitalmars.com...
> Nick Sabalausky:
>> Even if it weren't for that, I would still consider this important enough
>> to
>> be worth the hassle of changing it. It would be better than letting D
>> forever maintain the cruft of a particularly bad design decision (no
>> offense, Walter) in the same way that C++ would.
>
> But I am not sure that proposed idea is the best, because in Python (that acts like that) you often enough write for mistake:
>
> x = foo
>
> Forgetting the (). In this case x gets a (kind of) reference to foo and not to its result. You can do something similar in that D proposal:
>
> auto x = foo
>
> So I think &foo and foo() are more explicit and better (better == less error-prone), to represent the pointer/delegate/closure, and to represent the calling.
>

Yes, but 1. As you indicated, it could only happen in D when using an initializer on an "auto". And 2. I would imagine that would probably get caught as soon x was used.

But, if &foo is deemed to be better for referring to the function itself (ie without invoking), then using "foo" without "&" or "()" should be prohibited. (In fact, maybe that would be the ideal solution?)


January 11, 2009
Nick Sabalausky:
> Yes, but 1. As you indicated, it could only happen in D when using an initializer on an "auto". And 2. I would imagine that would probably get caught as soon x was used.

You are right, Python being dynamically typed the situation is a little worse there.


> then using "foo" without "&" or "()" should be prohibited. (In fact, maybe that would be the ideal solution?)

That's what I was saying, to disallow "foo" without () or &. It's not the ideal situation but to me it looks better than the current ones (of both Python and D1).

Bye,
bearophile
January 11, 2009
Andrei Alexandrescu 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.
> 
	Won't work: how do you then create a write-only property?

		Jerome
- --
mailto:jeberger@free.fr
http://jeberger.free.fr
Jabber: jeberger@jabber.fr
January 11, 2009
On Sun, 11 Jan 2009 21:52:27 +0300, bearophile <bearophileHUGS@lycos.com> wrote:

> Nick Sabalausky:
>> Yes, but 1. As you indicated, it could only happen in D when using an
>> initializer on an "auto". And 2. I would imagine that would probably get
>> caught as soon x was used.
>
> You are right, Python being dynamically typed the situation is a little worse there.
>
>
>> then using "foo" without "&" or "()" should be
>> prohibited. (In fact, maybe that would be the ideal solution?)
>
> That's what I was saying, to disallow "foo" without () or &. It's not the ideal situation but to me it looks better than the current ones (of both Python and D1).
>
> Bye,
> bearophile

Yes, this is the best design so far.

I'd also note that using foo without either "&" or "()" is still necessary to get access to foo's set of properties:

auto s = foo.stringof;
auto m = foo.mangleof;
// etc

Other than that I'm absolutely agree with both of you.
Too bad language designers don't participate in the discussion.
January 11, 2009
Denis Koroskin wrote:
> On Thu, 08 Jan 2009 03:45:08 +0300, Vishaal <vishaal@nospam.com> wrote:
> 
>> Properties, such as array.length, should return lvalues to allow:
>> a.length += 8;
>> or other similar statements.
> 
> I'd like to point out another related issue that everyone seems to miss.
> 
> The following code is taken from a GUI library:
> 
> struct Rect
> {
>    int x, y, width, height;
>    void reset() { x = y = width = height = 0; }
> }
> 
> class Control
> {
>    //...
> 
>    Rect rect()
>    {
>        return _rect;
>    }
> 
>    void rect(Rect newRect)
>    {
>        _resizeControl(newRect);
>    }
> 
>    void _resizeControl(Rect rect)
>    {
>        // ...
>    }
> 
>    private Rect _rect;
>    //...
> }
> 
> Imagine rect is not a property but a field, first. How would you mutate it? I'd do it as follows:
> 
> Control c = new Control();
> c.rect.reset();
> c.rect.width = 100;
> 
> Both lines do nothing when field replaced with a property. Code is broken but there is no complains from compiler.
> You should write the following code instead:
> 
> Control c = new Control();
> auto tmp = c.rect;
> tmp.reset();
> c.rect = tmp;
> 
> auto tmp = c.rect;
> tmp.width = 100;
> c.rect = tmp;
> 
> but it doesn't look good. Compiler could be smarter in this regard - it could generate the code above automatically whenever a mutating method is called on a property.
> 
> And here is also another issue I can't wait to be fixed. The following syntax:
> auto prop = foo.prop();
> 
> works for properties but not for fields, meaning that whenever code author decides to change it from property to field, user code is broken. Properties should not have optional braces!
> 
> As a result, properties and fields can not be used interchangeably until issues above are fixed.

This is a very strong argument. The issue is related to the fact that calling a member function is allowed on an rvalue, an anomaly that D inherited from C++.

Andrei
January 11, 2009
On Mon, Jan 12, 2009 at 4:07 AM, "Jérôme M. Berger" <jeberger@free.fr> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Andrei Alexandrescu 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.
>>
>        Won't work: how do you then create a write-only property?

I'm guessing they thought of that and the answer is you can't, but write-only properties are a rare corner case.

But either way, it doesn't solve the ambiguity problem.  A callback setter/getter pair will still run into trouble because you can't tell if the getter wants to get the callback or actually call it.

--bb