August 02, 2009
Ary Borenszweig wrote:
> 
> What I'd like the compiler to do, if you don't define property+=, is to transform this:
> 
> 1. foo.property += 2;
> 
> into this:
> 
> 2. foo.property = foo.property + 2;
> 

Be careful.

It's actually better to transform it into

auto t = foo.property;
t += 2;
foo.property = t;

The reason is because typeof(t) may have opAddAssign defined, but no
definition for opAdd or opAdd_r.

Other than that, I'm totally with you.
August 02, 2009
Ary Borenszweig wrote:

> What I'd like the compiler to do, if you don't define property+=, is to transform this:
> 
> 1. foo.property += 2;
> 
> into this:
> 
> 2. foo.property = foo.property + 2;

> Walter: what are the technical reasons for not transforming 1 into 2 already?

Because there is no guarantee that += and + are implemented consistently by user-defined types (even though they should be). A better transformation, suggested by several people, is:

{
    auto temp = foo.property;
    temp += 2;
    foo.property = temp;
}

-- 
Michiel Helvensteijn

August 02, 2009
JPF schrieb:
> Michiel Helvensteijn schrieb:
>> Michiel Helvensteijn wrote:
>>
>>> --------------------------------------------------
>>> bool empty {
>>>     void set(auto value) { ... }
>>>     auto get() { ... }
>>> }
>>>
>>> empty = false; // empty.set(false)
>>> auto b = empty; // auto b = empty.get()
>>> --------------------------------------------------
>>>
>>> for example, requires no hacks and no keywords. And has the added
>>> advantage that you can still use the getter and setter methods directly.
>> It should be noted that there is an ambiguity if the type of the property is
>> a struct/class with members named 'get' and 'set'. As I see it, there are
>> three ways to resolve it:
>>
>> * Disallow properties with such a struct/class. This seems a little bit
>> excessive and silly. But it is one way.
>>
>> * The 'set' and 'get' from the property are only used for the
>> property-calling syntax. They can not be referenced directly. The members
>> of the struct/class would all be accessable. This would work about the same
>> way as, for example, the suggestion from John C in this thread. And if you
>> go down this path, you might as well condense the syntax, as he did.
>>
>> * The 'set' and 'get' from the property are accessable functions and they
>> overshadow possible member functions with those names.
>>
>> My language uses the third way, but there is no problem with overshadowing.
>> The 'set' and 'get' functions have the same special purpose for every type,
>> and the property is meant to override them.
>>
>> I guess D could do something similar using, instead of my 'get' and 'set',
>> D's 'this' and 'opAssign' respectively.
>>
> There's at least one more solution:
> define the property as
> --------------------------------------------------
>>> bool empty {
>>>     void set(auto value) { ... }
>>>     auto get() { ... }
>>> }
> --------------------------------------------------
> but rewrite empty.get/set to empty.__get/__set. As far as I know names
> beginning with __ are reserved, so the returned type of the property
> couldn't define it. Accessing the setter/getter directly could still be
> done using
> --------------------------------------------------
> empty = false; // empty.__set(false)
> auto b = empty; // auto b = empty.__get()
> 
> auto getter = &empty.__get()
> --------------------------------------------------
> This also allows getting function pointers for the setter and the
> getter. As an addition
> --------------------------------------------------
> auto b = &empty
> --------------------------------------------------
> would then return a pointer to the returned value.

But you would have to write more than necessary. Simpler is:
---
bool foo {
	in(bar) { ... }
	out { return ... }
}
---
in is translated to: void in(bool bar) {...}
out is translated to: bool out() {...}

To get a delegate to in:
auto f = &foo.in;

foo = 5; is equivalent to foo.in(5);

This way you don't need any new keywords or ugly (double) underscores.
And it's unambiguous and pretty clear.
August 02, 2009
Denis Koroskin wrote:
> On Sun, 02 Aug 2009 13:00:38 +0400, Michiel Helvensteijn <m.helvensteijn.remove@gmail.com> wrote:
> 
>> Walter Bright wrote:
>>
>>>    bool empty { ... }
>>>    void empty=(bool b) { ... }
>>>
>>> The only problem is when a declaration but not definition is desired:
>>>
>>>    bool empty;
>>>
>>> but oops! That defines a field. So we came up with essentially a hack:
>>>
>>>    bool empty{}
>>>
>>> i.e. the {} means the getter is declared, but defined elsewhere.
>>>
>>> What do you think?
>>
>> It is quite hack-ish. There are ways to have your cake and eat it too. I
>> wouldn't settle for 'bool empty{}'.
>>
>> --------------------------------------------------
>> bool empty {
>>     void set(auto value) { ... }
>>     auto get() { ... }
>> }
>>
>> empty = false; // empty.set(false)
>> auto b = empty; // auto b = empty.get()
>> --------------------------------------------------
>>
>> for example, requires no hacks and no keywords. And has the added advantage
>> that you can still use the getter and setter methods directly. To call them
>> or get delegates from them.
>>
> 
> I agree, this is a better solution!

I'd like to have an easy enough syntax for defining read-only properties (often in my code). With the proposed syntax, one writes

bool empty { ... }

and calls it a day, but with the elaborate getters and setters there are two scopes to get through:

bool empty { auto get() { ... } }

which is quite some aggravation.


Andrei
August 02, 2009
Andrei Alexandrescu wrote:

> I'd like to have an easy enough syntax for defining read-only properties (often in my code). With the proposed syntax, one writes
> 
> bool empty { ... }
> 
> and calls it a day, but with the elaborate getters and setters there are two scopes to get through:
> 
> bool empty { auto get() { ... } }
> 
> which is quite some aggravation.

The point is not really the grouping of elements within brackets. That just eliminates some redundancy. It can also look like the following:

void empty.set(bool value) { ... }
bool empty.get() { ... }

and have the same meaning as my earlier example.

-- 
Michiel Helvensteijn

August 02, 2009
Jarrett Billingsley wrote:
> I think it's funny that for a week, Andrei has been arguing against
> throwing around new syntax to solve this problem, and that's exactly
> what you guys have come up with.  Really, how much more complicated
> would this make the parser, compared to adding a new attribute?

We couldn't find a good solution without adding new syntax, so this is now on the table. Adding syntax or keywords is the next thing to look at. I'd still be unsatisfied if:

(a) there would be significant syntactic noise to defining a read-only property

(b) we had to add a keyword


Andrei
August 02, 2009
Sun, 02 Aug 2009 00:43:43 -0700, Walter Bright wrote:

> Having optional parentheses does lead to unresolvable ambiguities. How much of a problem that really is is debatable, but let's assume it should be resolved. To resolve it, a property must be distinguishable from a regular function.
> 
> One way is to simply add a "property" attribute keyword:
>
> The problem is that:
> 
> 1. there are a lot of keywords already
> 2. keywords are global things
> 
> The alternative is to have a unique syntax for properties. Ideally, the syntax should be intuitive and mimic its use. After much fiddling, and based on n.g. suggestions, Andrei and I penciled in:
> 
>    bool empty { ... }
>    void empty=(bool b) { ... }
> 
> [snip]
> 
>    bool empty{}

I don't like this part.  When I look at this syntax I think about weird corner cases which will surface sooner or later.

You still didn't voice your opinion on annotations.  But if you do consider them useful and think that they will get into the compiler sooner or later, I propose this solution:

1.  Hack the front-end to allow '@' in *keywords*
2.  Add a "@property" keyword

This solution:

*  Cancels the "keywords are global" concern: @property can never
interfere with user-defined symbols
*  Does not add a keyword to the specs: @property being a keyword is
merely an implementation detail which goes away as soon as arbitrary
annotations are supported by the compiler
*  Implementation complexity is roughly the same as for simple keyword
addition which I believe is less complex than specialized syntaxes like
prop=()
August 02, 2009
Michel Fortin wrote:
> On 2009-08-02 03:43:43 -0400, Walter Bright <newshound1@digitalmars.com> said:
> 
>> The alternative is to have a unique syntax for properties. Ideally, the syntax should be intuitive and mimic its use. After much fiddling, and based on n.g. suggestions, Andrei and I penciled in:
>>
>>    bool empty { ... }
>>    void empty=(bool b) { ... }
> 
> Looking at it more carefully, this looks like an invitation to omit parenthesis for functions with no argument. I mean, look at this and tell me what it is?
> 
>     T transform { ... }
> 
> Is this a transform property (returning and affine transform) or an action function returning transform? I'd guess it's a property since it has no parenthesis, but nothing makes this very clear.
> 
> And could you do this? Would Andrei be tempted by this?
> 
>     void popFront { ... }

Good point! I continue to be unhappy about the designer having to think about inconsequentials like this.

> Note that I'm brigning this as an observation. Style guidelines can be written mandating parenthesis for actions functions, which means my problem of writing a coherent naming guideline is solved. But who read the style guidelines?

Yes, yes, excellent point.

> While I like this syntax, the "getProperty()"/"setProperty()" syntax (and also the "property" keyword syntax) has one advantage over this one: it forces the interface to explicitly say "this is a getter/setter" or "this is a property", which I expect would reduce abuses. It's the same difference between as "opAdd" vs. "op+".

Walter made a compiler writer's point - now many symbols would have to be looked up twice instead of once. That is quite out of sync with everything else in the language.


Andrei
August 02, 2009
Marianne Gagnon wrote:
>> The alternative is to have a unique syntax for properties. Ideally, the syntax should be intuitive and mimic its use. After much fiddling, and based on n.g. suggestions, Andrei and I penciled in:
>>
>>    bool empty { ... }
>>    void empty=(bool b) { ... }
>>
>> The only problem is when a declaration but not definition is desired:
>>
>>    bool empty;
>>
>> but oops! That defines a field. So we came up with essentially a hack:
>>
>>    bool empty{}
>>
>> i.e. the {} means the getter is declared, but defined elsewhere.
>>
>> What do you think?
> 
> I liked the original idea... but this declaration syntax is a total can of worms. Like others pointed out, would the compiler automatically turn all functions with empty bodies into declarations? Would empty setters be considered a declaration? What if I actually *want*
>  to use an empty body as definition? Or what if I accidentally leave a body empty when I didn't want to?
> 
> Like someone else pointed out, existing keywords could be reused :
> 
> bool empty
> {
>     in(bool value)
>     {
>         _my_empty = value;
>     }
>     out
>     {
>         return _my_empty;
>     }
> }
> 
> I like this quite a bit.  I never wrote any compiler, granted, but I don't think it'd be that hard to implement - and doesn't introduce any new keyword.

Please, please, could we look at something that does NOT go through two scopes to get to the code?

> Or, alternatively, if you really wish to keep them separate, bool empty= { ... } isn't intuitive, as Andrei pointed out, but is already less error-prone than the empty-body declaration idea I believe

I think void empty=(bool b) { ... } is a net win, which the forced bool empty=() diminishes. It would be great to keep the setter and find something as nice for a getter.


Andrei
August 02, 2009
> ---
> bool foo {
>     in(bar) { ... }
>     out { return ... }
> }
> ---

Actually it's also enough with the surrounding scope.
And fast to write, just one line:
bool foo in(bar) {...} out {...}

Everyone that sees this for the first time can see what it means. And it's more intuitive syntax than

  bool empty { ... }
  void empty=(bool b) { ... }

With the first syntax above you would have to specify the type (bool in this case) only once.