August 02, 2009
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!
August 02, 2009
Frank Benoit wrote:
> Walter Bright schrieb:
>> Zhenyu Zhou wrote:
>>> Walter Bright Wrote:
>>>> but oops! That defines a field. So we came up with essentially a hack:
>>>>
>>>>    bool empty{}
>>> weird syntax
>> I agree, it's a wart.
>>
>>
>>> I'd rather use
>>>    bool empty=() { ... }
>>>    void empty=(bool b) { ... }
>> I suggested that, but Andrei thought it looked unintuitive, and he has a
>> point.
> 
> Or how about making it a single method?
> 
> bool empty=(bool* value){
> 	if( value ) _empty = *value;
> 	return _empty;
> }
> 
> The compiler rewrites the calling code to either pass the address or null.

So properties can't be used in SafeD?
August 02, 2009
On 2009-08-02 06:27:27 -0400, Michel Fortin <michel.fortin@michelf.com> said:

>>    bool empty{}
>> 
>> i.e. the {} means the getter is declared, but defined elsewhere.
>> 
>> What do you think?
> 
> I'd prefer this, which can't be misinterpreted as an empty statement:
> 
> 	bool empty { ... }

In the same vein, I'm now realizing that "bool empty {}" syntax for a declaration is also a little dangerous and inconsistent: contrary to other functions with a return value, the compiler can't issue an error to say you forgot to return a value if you leave the body empty, it'd silently transform it to a declaration instead.

Again, the elipsis solves this.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

August 02, 2009
John C schrieb:
> 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:
>>
>>   property bool empty() { ... }
>>   property void empty(bool b) { ... }
>>
>> The problem is that:
>>
>> 1. there are a lot of keywords already
>> 2. keywords are global things
> 
> Well, property probably isn't too common a variable name, so it shouldn't impact existing code.
> 
>>
>> 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.
> 
> Would unimplemented setters look like this:
> 
> void empty = (bool b) {}
> 
> ?
> 
>>
>> What do you think?
> 
> Looks a bit odd. Perhaps it's just the unfamiliarity of the syntax. Most of us got used to templates, eventually.
> 
> My own syntax suggestion requires no new keywords (contextual or otherwise).
> 
> interface INameable {
> 
>   string name {
>     ();
>     (value);
>   }
> 
> }
> 
> class Person : INameable {
> 
>   private string name_;
> 
>   string name {
>     () { return name_; }
>     (value) { name_ = value; }
>   }
> 
> }
> 
> In the above example, "value" could be anything the class designer wants - to the compiler, empty parentheses () represent the getter, (blah) the setter.

Looks good. You could have wrapper properties like:
---
class Clock {
	private int sec_;
	int min {
		() {return sec_ / 60;}
		(m) {sec_ = m * 60;}
	}
}
---
auto c = new Clock;
c.min = 2;
++c.min; // gets translated to "c.min = c.min + 1;" and evaluates to c.min called after that call
c.min++; // gets translated to "c.min = c.min + 1;" and evaluates to c.min called before that call
// same with other ops unless they are explicitely otherwise defined
---

(And all non-property functions shouldn't be allowed to be called in assign-style or without parentheses.)
August 02, 2009
Walter Bright Wrote:
> One way is to simply add a "property" attribute keyword:
> 
>    property bool empty() { ... }
>    property void empty(bool b) { ... }
> 
> The problem is that:
> 
> 1. there are a lot of keywords already
> 2. keywords are global things

Have you thought about reusing existing keywords?
like "in" and "out"

August 02, 2009
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.

-- 
Michiel Helvensteijn

August 02, 2009
On Sun, Aug 2, 2009 at 3:43 AM, Walter Bright<newshound1@digitalmars.com> 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:
>
>  property bool empty() { ... }
>  property void empty(bool b) { ... }
>
> 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) { ... }

The *very* first thing I thought of when I saw this was:

virtual void foo() = 0;

I mean, why do we need the abstract keyword when C++ already has a perfectly obvious, eminently understandable syntax for it?

Right?

> 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 think this feels like a desperate grasping-at-straws attempt to not add a keyword (even though pure, nothrow, shared, __gshared, and immutable all seem to have made it in without any great fanfare). Throwing esoteric syntax at it complicates the grammar and the parser, and you end up with this wad of symbols that doesn't intuitively indicate that it is a property.  Yes, you can get used to anything. People get used to Perl, too.

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?
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) { ... }
> 
> I like that. But then (just a question) can you do:
> 
>     void empty+=(bool b) { ... }
>     void empty++ { ... }
>     void ++empty { ... }
> 
> ?
> 

If we apply rewriting rules to expressions that are mutated (either by a unary operator or by being the left-hand side of some kind of assignment expression) then we get these for free.

I'd really like to /not/ have to define these extra operations. Otherwise we end up with one of the downsides of current operator overloads: defining all of them is a serious pain in the butt, and getting the compiler to define all of them for you is ugly.
August 02, 2009
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.


I have not been following the property discussion. As far as syntactic ambiguities, is there anything else besides returning a delegate? If proprties are added to D, will a class designer decide when parenthesis should be added/omitted for zero argument functions?
August 02, 2009
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 { ... }

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?

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

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/