www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - property / getProperty() / setProperty()

reply Michel Fortin <michel.fortin michelf.com> writes:
I hope this proposal can rally more that divide... let's see.

Andrei said this in another thread about adding a property keyword in 
front of functions to make them properties:

 The problem is that it's all loss, no gain: the callee must make the
 decision whether the call must be with or without parens, and the caller
 must obey that decision. There is no guarantee gained, only effort.

I see your point Andrei: it's little gain to add a syntax that's just a modifier to a function to decide how you must call it. I also see the point of all those arguing that it's important to be able to distinguish between a property and an action, and that the english laguage is not expressive enough to make that distinction clear in a lot of cases. I know, I've written programming guidelines[1] and tried very hard to make this problem go away by mandating "is", "has" or a modal verb as a prefix for boolean attributes in the guidelines, only to be stuck with no solution for the "transform" example from Bill Baxter (thread "Properties - another one that gets me") which isn't boolean and for which you can't really add a prefix that makes sense. [1]: http://prowiki.org/wiki4d/wiki.cgi?DProgrammingGuidelines The best simple solution to that property problem I've seen up to now is to define "getProperty" and "setProperty" and have the compiler automatically check for these functions when it encounters the "property" symbol. Why do I favor "getThing" and "setThing" over "opGet_thing" and "opSet_thing"? Because the later are ugly. Please don't underestimate aestetics and readability as those are the key to make the language enjoyable to use and what the beginners will judge the language from. Also, the pattern will be pretty familiar to those comming from Java and elsewhere. And finally, for those who don't like having a property syntax, they can ignore properties completely and continue to use the get/set functions directly without making their code ugly. Here's an example: ~~~ int getValue(); void setValue(int x); setValue(1); /* property: */ value = 1; assert(getValue() == 1); /* property: */ assert(value == 1); ~~~ The problems this syntax should fix are: 1. the ambiguity between actions and properties: getValue()/setValue() are functions and thus actions named with verbs ("get" and "set"), but you can access them as the "value" property too, which is a noun that will call the function as necessary when an action is needed. (As a bonus, this makes "writeln = 2" illegal.) 2. the inconsistency for functions and properties returning something such as a delegate or a struct or class with an opCall member, where you absolutely need to write the function with a parenthesis to actually call the returned value. You can either call the function "getMyDelegate()(delegate_arg)" or use the property "myDelegate(delegate_arg)" just as you can with a field. This syntax doesn't solve the operator overloading issue. It isn't meant to do that either: properties should stay simple. The two small problems it pose are: 1. There's an ambiguity when another symbol is named after the property name that would call the get/set function. I suggest that this other symbol simply hide the property. 2. You need an uppercase algorithm in the compiler to be able to translate "property" to "setProperty" and "getProperty" and do the proper lookup. This works well for ASCII, but can it go messy with Unicode? To avoid converting to unicode upercase, we could use "get_thing" and "set_thing" (nicer than opGet/opSet), although that doesn't really fit with the coding standards of D. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 01 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 I hope this proposal can rally more that divide... let's see.
 
 Andrei said this in another thread about adding a property keyword in 
 front of functions to make them properties:
 
 The problem is that it's all loss, no gain: the callee must make the
 decision whether the call must be with or without parens, and the caller
 must obey that decision. There is no guarantee gained, only effort.

I see your point Andrei: it's little gain to add a syntax that's just a modifier to a function to decide how you must call it.

That's a great summary.
 I also see the point of all those arguing that it's important to be able 
 to distinguish between a property and an action, and that the english 
 laguage is not expressive enough to make that distinction clear in a lot 
 of cases.

I understand that point too.
 I know, I've written programming guidelines[1] and tried very 
 hard to make this problem go away by mandating "is", "has" or a modal 
 verb as a prefix for boolean attributes in the guidelines, only to be 
 stuck with no solution for the "transform" example from Bill Baxter 
 (thread "Properties - another one that gets me") which isn't boolean and 
 for which you can't really add a prefix that makes sense.
 
 [1]: http://prowiki.org/wiki4d/wiki.cgi?DProgrammingGuidelines

Good point.
 The best simple solution to that property problem I've seen up to now is 
 to define "getProperty" and "setProperty" and have the compiler 
 automatically check for these functions when it encounters the 
 "property" symbol.
 
 Why do I favor "getThing" and "setThing" over "opGet_thing" and 
 "opSet_thing"? Because the later are ugly. Please don't underestimate 
 aestetics and readability as those are the key to make the language 
 enjoyable to use and what the beginners will judge the language from. 
 Also, the pattern will be pretty familiar to those comming from Java and 
 elsewhere. And finally, for those who don't like having a property 
 syntax, they can ignore properties completely and continue to use the 
 get/set functions directly without making their code ugly.

I also like getThing and setThing more than get_thing and set_thing for defining a property called "thing". They both have problems, though: the former can't define a property starting with an uppercase letter, and the latter can't define a property starting with an underscore. (Symbols can't contain two underscores.) Ideas?
 Here's an example:
 
 ~~~
 int getValue();
 void setValue(int x);
 
 setValue(1);              /* property: */  value = 1;
 assert(getValue() == 1);  /* property: */  assert(value == 1);
 ~~~
 
 The problems this syntax should fix are:
 
 1. the ambiguity between actions and properties: getValue()/setValue() 
 are functions and  thus actions named with verbs ("get" and "set"), but 
 you can access them as the "value" property too, which is a noun that 
 will call the function as necessary when an action is needed. (As a 
 bonus, this makes "writeln = 2" illegal.)

Cool. If I only defined getEmpty, to I get to still use empty?
 2. the inconsistency for functions and properties returning something 
 such as a delegate or a struct or class with an opCall member, where you 
 absolutely need to write the function with a parenthesis to actually 
 call the returned value. You can either call the function 
 "getMyDelegate()(delegate_arg)" or use the property 
 "myDelegate(delegate_arg)" just as you can with a field.

Very nice solution indeed.
 This syntax doesn't solve the operator overloading issue. It isn't meant 
 to do that either: properties should stay simple.

Which issue are you referring to? +=?
 The two small problems it pose are:
 
 1. There's an ambiguity when another symbol is named after the property 
 name that would call the get/set function. I suggest that this other 
 symbol simply hide the property.

I wonder what should happen when this happens across scopes, e.g. in base and derived classes.
 2. You need an uppercase algorithm in the compiler to be able to 
 translate "property" to "setProperty" and "getProperty" and do the 
 proper lookup. This works well for ASCII, but can it go messy with Unicode?

Good question.
 To avoid converting to unicode upercase, we could use "get_thing" and 
 "set_thing" (nicer than opGet/opSet), although that doesn't really fit 
 with the coding standards of D.

Also, again, if you want to define "_thing" you'd have to write "get__thing" and "set__thing". Maybe we could lift the restriction about two underscores and only keep it for two leading underscores. Andrei
Aug 01 2009
next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 11:31 AM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:

 To avoid converting to unicode upercase, we could use "get_thing" and
 "set_thing" (nicer than opGet/opSet), although that doesn't really fit with
 the coding standards of D.

Also, again, if you want to define "_thing" you'd have to write "get__thing" and "set__thing". Maybe we could lift the restriction about two underscores and only keep it for two leading underscores.

I'm pretty sure that's what the restriction is now (no leading double underscores). I don't think a__b is reserved.
Aug 01 2009
prev sibling next sibling parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 11:42 AM, Jarrett
Billingsley<jarrett.billingsley gmail.com> wrote:
 On Sat, Aug 1, 2009 at 11:31 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:

 To avoid converting to unicode upercase, we could use "get_thing" and
 "set_thing" (nicer than opGet/opSet), although that doesn't really fit =



 the coding standards of D.

Also, again, if you want to define "_thing" you'd have to write "get__th=


 and "set__thing". Maybe we could lift the restriction about two undersco=


 and only keep it for two leading underscores.

I'm pretty sure that's what the restriction is now (no leading double underscores). =A0I don't think a__b is reserved.

It is. "Identifiers starting with __ (two underscores) are reserved."
Aug 01 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Sat, Aug 1, 2009 at 11:42 AM, Jarrett
 Billingsley<jarrett.billingsley gmail.com> wrote:
 On Sat, Aug 1, 2009 at 11:31 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:

 To avoid converting to unicode upercase, we could use "get_thing" and
 "set_thing" (nicer than opGet/opSet), although that doesn't really fit with
 the coding standards of D.

and "set__thing". Maybe we could lift the restriction about two underscores and only keep it for two leading underscores.

underscores). I don't think a__b is reserved.

It is. "Identifiers starting with __ (two underscores) are reserved."

Thanks. So it looks like get_property() and set_property() could fly. How does that sound? Andrei
Aug 01 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could fly. 
 How does that sound?

Not too much good. Among the simpler solutions there's the 'property' attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly. There are also other alternative (and a little more complex) solutions (inspired by C# too), that allow to reduce boilerplate code. I have asked for one of them more than one year ago. They aren't hard to learn. Bye, bearophile
Aug 01 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could fly. 
 How does that sound?

Not too much good. Among the simpler solutions there's the 'property' attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

We can't throw keywords at problems like they're getting out of style. I've noticed that here every little problem gets solved by a little keyword. If not, some arcane new syntax. Nobody seems to care about rewriting, which I think is best. Andrei
Aug 01 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu escribió:
 bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could fly. 
 How does that sound?

Not too much good. Among the simpler solutions there's the 'property' attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

We can't throw keywords at problems like they're getting out of style. I've noticed that here every little problem gets solved by a little keyword. If not, some arcane new syntax. Nobody seems to care about rewriting, which I think is best.

So what do you think about introducing attributes? Not only it will help not introducing new keyword, but it'll also *reduce* the amount of keywords that exist right now.
Aug 01 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ary Borenszweig wrote:
 Andrei Alexandrescu escribió:
 bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could 
 fly. How does that sound?

Not too much good. Among the simpler solutions there's the 'property' attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

We can't throw keywords at problems like they're getting out of style. I've noticed that here every little problem gets solved by a little keyword. If not, some arcane new syntax. Nobody seems to care about rewriting, which I think is best.

So what do you think about introducing attributes? Not only it will help not introducing new keyword, but it'll also *reduce* the amount of keywords that exist right now.

Attributes would be great, but you guys should stop asking me what I think and ask Walter. I seem to vaguely recall Walter isn't very excited about attributes. Andrei
Aug 01 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Sat, Aug 1, 2009 at 12:21 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could fly. How
 does that sound?

attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

noticed that here every little problem gets solved by a little keyword. If not, some arcane new syntax. Nobody seems to care about rewriting, which I think is best.

I don't know if you're just being passive-aggressive here or what. Is this a response to my post? I'll ask again: do you have any *technical* issues with the 'property' attribute suggestion?

My main technical issue is throwing a keyword at a very minor issue. Once the keyword is in the mix, we need to define how it interacts with everything else (e.g., are properties overridable?) A solution based on rewrites is considerably simpler and more in according with the size of the problem. Andrei
Aug 01 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu escribió:
 Jarrett Billingsley wrote:
 On Sat, Aug 1, 2009 at 12:21 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could 
 fly. How
 does that sound?

attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

style. I've noticed that here every little problem gets solved by a little keyword. If not, some arcane new syntax. Nobody seems to care about rewriting, which I think is best.

I don't know if you're just being passive-aggressive here or what. Is this a response to my post? I'll ask again: do you have any *technical* issues with the 'property' attribute suggestion?

My main technical issue is throwing a keyword at a very minor issue. Once the keyword is in the mix, we need to define how it interacts with everything else (e.g., are properties overridable?) A solution based on rewrites is considerably simpler and more in according with the size of the problem.

The "property" just signals that the function is a property. But it's still a function and all of the previous rules that existed are still valid. I'll copy Jarrett's points here once more: 1. You can no longer call functions as properties that were never intended to be (writeln = 4; goes away). 2. The "obj.prop(args)" ambiguity goes away. *Either* obj.prop is a normal method function and (args) are passed to it, *or* obj.prop has the "property" attribute, and (args) are passed to its result. Stuff like "obj.prop[i]" is the same way. 3. There is no naming ambiguity. 4. There are no case issues. 5. It provides useful semantic information to tools, IDEs, and reflection. 6. It's nonintrusive and self-documenting. As you can see, the only thing that will change for users is point 1. Nothing else changes, no need to define new rules, new syntax, new nothing. It's as unobstrusive as possible (obviusly much better if attributes were already present in the language). About attributes, later I'll write a post about how attribute can be started to be implemented (not just the syntax, but what the compiler does with them).
Aug 01 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Ary Borenszweig wrote:
 The "property" just signals that the function is a property. But it's
 still a function and all of the previous rules that existed are still
 valid.

My problem with the 'property' syntax: Possibility 1: the property still acts like a function, so you can still do 'x.a()' when you mean 'x.a'. Possibility 2: the property does not act like a function, so you can no longer get a delegate to the property getter. Possibility 3: the property sometimes acts like a function and sometimes not, and you haven't defined the distinction. All three possibilities are messy, and I can't tell from your proposal which one will apply. get_foo/set_foo is better in this regard, plus it doesn't require yet another keyword. -- Rainer Deyke - rainerd eldwood.com
Aug 01 2009
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Rainer Deyke escribió:
 Ary Borenszweig wrote:
 The "property" just signals that the function is a property. But it's
 still a function and all of the previous rules that existed are still
 valid.

My problem with the 'property' syntax: Possibility 1: the property still acts like a function, so you can still do 'x.a()' when you mean 'x.a'. Possibility 2: the property does not act like a function, so you can no longer get a delegate to the property getter. Possibility 3: the property sometimes acts like a function and sometimes not, and you haven't defined the distinction.

None of those are correct. See Jarrett's post. property { int x() { } int x(int a) { } } auto a = x; // OK auto a = x(); // Wrong x = 2; // OK x(2); // Wrong
Aug 01 2009
parent Rainer Deyke <rainerd eldwood.com> writes:
Jarrett Billingsley wrote:
 On Sat, Aug 1, 2009 at 2:38 PM, Ary Borenszweig<ary esperanto.org.ar> wrote:
 auto a = x; // OK
 auto a = x(); // Wrong
 x = 2; // OK
 x(2); // Wrong

And furthermore, I mentioned that &obj.foo would always get the address of the member 'foo' from 'obj', even if 'foo' was a property.

That's the part of this proposal I don't like. The getter of a property is not the property itself, and should not have the same name. It's confusing that '&x.y' is a delegate but 'x.y' is not a method. In short, this proposal fails to fix the conceptual problem with the way properties are handled in D right now. -- Rainer Deyke - rainerd eldwood.com
Aug 01 2009
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:h51rnq$o2q$1 digitalmars.com...
 Jarrett Billingsley wrote:
 I'll ask again: do you have any *technical* issues with the 'property'
 attribute suggestion?

My main technical issue is throwing a keyword at a very minor issue.

Yeah, it is pretty minor, huh? I mean, it's not like it's been the center of discussion for the past week. And no one has ever complained about it before. Downplaying the size of the issue at hand doesn't make it go away.
 Once the keyword is in the mix, we need to define how it interacts with 
 everything else (e.g., are properties overridable?)

Of course they're overridable. They are *functions*. They do everything exactly the same as other functions. *All* the property attribute would do is enforce a property syntax at the use site instead of a function call syntax.
 A solution based on rewrites is considerably simpler and more in according 
 with the size of the problem.

A solution based on rewrites has a pretty horrible problem with name ambiguity. And this isn't even a technical concern; you're just saying again that the problem is minor. You have not presented any technical arguments against the property attribute suggestion. So let me get this straight: the property attribute would be better technically, but let's not throw more keywords at it; so instead we suggest attributes, but no, they don't have any useful purpose. WHAT.
Aug 01 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:h51rnq$o2q$1 digitalmars.com...
 Jarrett Billingsley wrote:
 I'll ask again: do you have any *technical* issues with the 'property'
 attribute suggestion?


Yeah, it is pretty minor, huh? I mean, it's not like it's been the center of discussion for the past week. And no one has ever complained about it before. Downplaying the size of the issue at hand doesn't make it go away.
 Once the keyword is in the mix, we need to define how it interacts with 
 everything else (e.g., are properties overridable?)

Of course they're overridable. They are *functions*.

Then why are you calling them properties? :o)
 They do everything 
 exactly the same as other functions.  *All* the property attribute would do 
 is enforce a property syntax at the use site instead of a function call 
 syntax.

Oh, so it is minor.
 A solution based on rewrites is considerably simpler and more in according 
 with the size of the problem.

A solution based on rewrites has a pretty horrible problem with name ambiguity. And this isn't even a technical concern; you're just saying again that the problem is minor. You have not presented any technical arguments against the property attribute suggestion. So let me get this straight: the property attribute would be better technically, but let's not throw more keywords at it; so instead we suggest attributes, but no, they don't have any useful purpose. WHAT.

I didn't say that. Andrei
Aug 01 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Sat, Aug 1, 2009 at 1:38 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 
 Of course they're overridable.  They are *functions*.


Stop deliberately misunderstanding me.

Yeah, sorry. Low blow. I shouldn't have sent out that crap. Andrei
Aug 01 2009
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu escribió:
 bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could fly. 
 How does that sound?

Not too much good. Among the simpler solutions there's the 'property' attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

We can't throw keywords at problems like they're getting out of style.

Hey! Let's introduce pure functions --> the new "pure" keyword was added. Hey! Let's introduce functions that don't throw --> the new "nothrow" keyword was added. Hey! Let's introduce thread local storage --> "shared" and "__gshared" keyword added. Hey! Let's introduce... annotations and stop adding keywords for every new feature.
Aug 01 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ary Borenszweig wrote:
 Andrei Alexandrescu escribió:
 bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could 
 fly. How does that sound?

Not too much good. Among the simpler solutions there's the 'property' attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

We can't throw keywords at problems like they're getting out of style.

Hey! Let's introduce pure functions --> the new "pure" keyword was added. Hey! Let's introduce functions that don't throw --> the new "nothrow" keyword was added. Hey! Let's introduce thread local storage --> "shared" and "__gshared" keyword added. Hey! Let's introduce... annotations and stop adding keywords for every new feature.

For the record, I didn't like most of these. Andrei
Aug 01 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 11:54 AM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 On Sat, Aug 1, 2009 at 11:42 AM, Jarrett
 Billingsley<jarrett.billingsley gmail.com> wrote:
 On Sat, Aug 1, 2009 at 11:31 AM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:

 To avoid converting to unicode upercase, we could use "get_thing" and
 "set_thing" (nicer than opGet/opSet), although that doesn't really fi=





 with
 the coding standards of D.

Also, again, if you want to define "_thing" you'd have to write "get__thing" and "set__thing". Maybe we could lift the restriction about two underscores and only keep it for two leading underscores.

I'm pretty sure that's what the restriction is now (no leading double underscores). =A0I don't think a__b is reserved.

It is. "Identifiers starting with __ (two underscores) are reserved."

Thanks. So it looks like get_property() and set_property() could fly. How does that sound?

See my other reply.
Aug 01 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 12:21 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 bearophile wrote:
 Andrei Alexandrescu:
 Thanks. So it looks like get_property() and set_property() could fly. How
 does that sound?

Not too much good. Among the simpler solutions there's the 'property' attribute, that while not helping in reducing code (it makes code longer!) solves most problems, while being simple. It's the minimal solution that I think will work/fly.

We can't throw keywords at problems like they're getting out of style. I've noticed that here every little problem gets solved by a little keyword. If not, some arcane new syntax. Nobody seems to care about rewriting, which I think is best.

I don't know if you're just being passive-aggressive here or what. Is this a response to my post? I'll ask again: do you have any *technical* issues with the 'property' attribute suggestion?
Aug 01 2009
prev sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-01 11:31:17 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Michel Fortin wrote:
 I hope this proposal can rally more that divide... let's see.
 
 Andrei said this in another thread about adding a property keyword in 
 front of functions to make them properties:
 
 The problem is that it's all loss, no gain: the callee must make the
 decision whether the call must be with or without parens, and the caller
 must obey that decision. There is no guarantee gained, only effort.

I see your point Andrei: it's little gain to add a syntax that's just a modifier to a function to decide how you must call it.

That's a great summary.
 I also see the point of all those arguing that it's important to be 
 able to distinguish between a property and an action, and that the 
 english laguage is not expressive enough to make that distinction clear 
 in a lot of cases.

I understand that point too.
 I know, I've written programming guidelines[1] and tried very hard to 
 make this problem go away by mandating "is", "has" or a modal verb as a 
 prefix for boolean attributes in the guidelines, only to be stuck with 
 no solution for the "transform" example from Bill Baxter (thread 
 "Properties - another one that gets me") which isn't boolean and for 
 which you can't really add a prefix that makes sense.
 
 [1]: http://prowiki.org/wiki4d/wiki.cgi?DProgrammingGuidelines

Good point.
 The best simple solution to that property problem I've seen up to now 
 is to define "getProperty" and "setProperty" and have the compiler 
 automatically check for these functions when it encounters the 
 "property" symbol.
 
 Why do I favor "getThing" and "setThing" over "opGet_thing" and 
 "opSet_thing"? Because the later are ugly. Please don't underestimate 
 aestetics and readability as those are the key to make the language 
 enjoyable to use and what the beginners will judge the language from. 
 Also, the pattern will be pretty familiar to those comming from Java 
 and elsewhere. And finally, for those who don't like having a property 
 syntax, they can ignore properties completely and continue to use the 
 get/set functions directly without making their code ugly.

I also like getThing and setThing more than get_thing and set_thing for defining a property called "thing". They both have problems, though: the former can't define a property starting with an uppercase letter,

Well, yes and no. You could map both the property "thing" and "Thing" to "setThing"/"getThing", thus making the first character of a property case-insensitive. That's a little awkward, though. But that's exactly what key-value coding does for getting and setting value in Objective-C [1]. [1]: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/Compliant.html and
 the latter can't define a property starting with an underscore. 
 (Symbols can't contain two underscores.) Ideas?

This has been shown to not be the case by Jarret. So set_thing and get_thing can work indeed. I don't like that underscore much though: it looks like a special syntax for properties that goes against the language style guidelines. Sure you can change the style guidelines to adopt them, but this syntax will still look out of place.
 Here's an example:
 
 ~~~
 int getValue();
 void setValue(int x);
 
 setValue(1);              /* property: */  value = 1;
 assert(getValue() == 1);  /* property: */  assert(value == 1);
 ~~~
 
 The problems this syntax should fix are:
 
 1. the ambiguity between actions and properties: getValue()/setValue() 
 are functions and  thus actions named with verbs ("get" and "set"), but 
 you can access them as the "value" property too, which is a noun that 
 will call the function as necessary when an action is needed. (As a 
 bonus, this makes "writeln = 2" illegal.)

Cool. If I only defined getEmpty, to I get to still use empty?

Exactly. You define "bool getEmpty()" and the compiler rewrites any call to a property "empty" as "getEmpty()".
 2. the inconsistency for functions and properties returning something 
 such as a delegate or a struct or class with an opCall member, where 
 you absolutely need to write the function with a parenthesis to 
 actually call the returned value. You can either call the function 
 "getMyDelegate()(delegate_arg)" or use the property 
 "myDelegate(delegate_arg)" just as you can with a field.

Very nice solution indeed.
 This syntax doesn't solve the operator overloading issue. It isn't 
 meant to do that either: properties should stay simple.

Which issue are you referring to? +=?

This, and any other operator of this kind (++, --, *=, etc.).
 
 The two small problems it pose are:
 
 1. There's an ambiguity when another symbol is named after the property 
 name that would call the get/set function. I suggest that this other 
 symbol simply hide the property.

I wonder what should happen when this happens across scopes, e.g. in base and derived classes.

And I wonder more what happens with the various protection attributes. :-)
 2. You need an uppercase algorithm in the compiler to be able to 
 translate "property" to "setProperty" and "getProperty" and do the 
 proper lookup. This works well for ASCII, but can it go messy with 
 Unicode?

Good question.

For instance, isn't ß a lowercase-only letter in German that gets traslated to SS in uppercase? (I'm not very familiar with German.) -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 01 2009
prev sibling next sibling parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 10:14 AM, Michel Fortin<michel.fortin michelf.com> w=
rote:

 The best simple solution to that property problem I've seen up to now is =

 define "getProperty" and "setProperty" and have the compiler automaticall=

 check for these functions when it encounters the "property" symbol.

 Why do I favor "getThing" and "setThing" over "opGet_thing" and
 "opSet_thing"? Because the later are ugly. Please don't underestimate
 aestetics and readability as those are the key to make the language
 enjoyable to use and what the beginners will judge the language from. Als=

 the pattern will be pretty familiar to those comming from Java and
 elsewhere. And finally, for those who don't like having a property syntax=

 they can ignore properties completely and continue to use the get/set
 functions directly without making their code ugly.

 Here's an example:

 ~~~
 int getValue();
 void setValue(int x);

 setValue(1); =A0 =A0 =A0 =A0 =A0 =A0 =A0/* property: */ =A0value =3D 1;
 assert(getValue() =3D=3D 1); =A0/* property: */ =A0assert(value =3D=3D 1)=

 ~~~

 The problems this syntax should fix are:

 1. the ambiguity between actions and properties: getValue()/setValue() ar=

 functions and =A0thus actions named with verbs ("get" and "set"), but you=

 access them as the "value" property too, which is a noun that will call t=

 function as necessary when an action is needed. (As a bonus, this makes
 "writeln =3D 2" illegal.)

 2. the inconsistency for functions and properties returning something suc=

 as a delegate or a struct or class with an opCall member, where you
 absolutely need to write the function with a parenthesis to actually call
 the returned value. You can either call the function
 "getMyDelegate()(delegate_arg)" or use the property
 "myDelegate(delegate_arg)" just as you can with a field.

 This syntax doesn't solve the operator overloading issue. It isn't meant =

 do that either: properties should stay simple.

 The two small problems it pose are:

 1. There's an ambiguity when another symbol is named after the property n=

 that would call the get/set function. I suggest that this other symbol
 simply hide the property.

 2. You need an uppercase algorithm in the compiler to be able to translat=

 "property" to "setProperty" and "getProperty" and do the proper lookup. T=

 works well for ASCII, but can it go messy with Unicode?

 To avoid converting to unicode upercase, we could use "get_thing" and
 "set_thing" (nicer than opGet/opSet), although that doesn't really fit wi=

 the coding standards of D.

It's been mentioned before, and I'll mention it again: a simple 'property' attribute that can be applied to any function. No new syntax, no get/set/value 'magic' keywords, just 'property.' Applying it to a function makes the compiler enforce the property syntax when using the functions. Any function that doesn't have the property attribute - which should be most functions - can't be treated as one. It doesn't require any special support from the compiler beyond what it currently does. It doesn't require any 'magic'. It doesn't require any verbose syntax. It solves pretty much all the problems. 1. You can no longer call functions as properties that were never intended to be (writeln =3D 4; goes away). 2. The "obj.prop(args)" ambiguity goes away. *Either* obj.prop is a normal method function and (args) are passed to it, *or* obj.prop has the "property" attribute, and (args) are passed to its result. Stuff like "obj.prop[i]" is the same way. 3. There is no naming ambiguity. 4. There are no case issues. 5. It provides useful semantic information to tools, IDEs, and reflection. 6. It's nonintrusive and self-documenting. The *only* technical issue I can come up with is if you had "property ref X foo()", where foo returned a reference to some value type. Then you do "&obj.foo" - what does this get the address of? To that end, I suggest that &obj.foo always gets the address of the member or method 'foo' from object 'obj', and &(obj.foo) would get the address of the return value of obj.foo. The extra parens in there say "really, I want you to evaluate the thing inside *first*". Andrei, I don't know your thoughts on this. I know you don't like the idea of introducing new syntax but this is really as minimalistic as you can get. Do you have any technical issues with this proposal? Is there a reason why you would choose the opGet_foo/get_foo proposal over this?
Aug 01 2009
next sibling parent Marianne Gagnon <auria.mg gmail.com> writes:
Jarrett Billingsley Wrote:

 On Sat, Aug 1, 2009 at 10:14 AM, Michel Fortin<michel.fortin michelf.com>
wrote:
 
 The best simple solution to that property problem I've seen up to now is to
 define "getProperty" and "setProperty" and have the compiler automatically
 check for these functions when it encounters the "property" symbol.

 Why do I favor "getThing" and "setThing" over "opGet_thing" and
 "opSet_thing"? Because the later are ugly. Please don't underestimate
 aestetics and readability as those are the key to make the language
 enjoyable to use and what the beginners will judge the language from. Also,
 the pattern will be pretty familiar to those comming from Java and
 elsewhere. And finally, for those who don't like having a property syntax,
 they can ignore properties completely and continue to use the get/set
 functions directly without making their code ugly.

 Here's an example:

 ~~~
 int getValue();
 void setValue(int x);

 setValue(1);              /* property: */  value = 1;
 assert(getValue() == 1);  /* property: */  assert(value == 1);
 ~~~

 The problems this syntax should fix are:

 1. the ambiguity between actions and properties: getValue()/setValue() are
 functions and  thus actions named with verbs ("get" and "set"), but you can
 access them as the "value" property too, which is a noun that will call the
 function as necessary when an action is needed. (As a bonus, this makes
 "writeln = 2" illegal.)

 2. the inconsistency for functions and properties returning something such
 as a delegate or a struct or class with an opCall member, where you
 absolutely need to write the function with a parenthesis to actually call
 the returned value. You can either call the function
 "getMyDelegate()(delegate_arg)" or use the property
 "myDelegate(delegate_arg)" just as you can with a field.

 This syntax doesn't solve the operator overloading issue. It isn't meant to
 do that either: properties should stay simple.

 The two small problems it pose are:

 1. There's an ambiguity when another symbol is named after the property name
 that would call the get/set function. I suggest that this other symbol
 simply hide the property.

 2. You need an uppercase algorithm in the compiler to be able to translate
 "property" to "setProperty" and "getProperty" and do the proper lookup. This
 works well for ASCII, but can it go messy with Unicode?

 To avoid converting to unicode upercase, we could use "get_thing" and
 "set_thing" (nicer than opGet/opSet), although that doesn't really fit with
 the coding standards of D.

It's been mentioned before, and I'll mention it again: a simple 'property' attribute that can be applied to any function. No new syntax, no get/set/value 'magic' keywords, just 'property.' Applying it to a function makes the compiler enforce the property syntax when using the functions. Any function that doesn't have the property attribute - which should be most functions - can't be treated as one. It doesn't require any special support from the compiler beyond what it currently does. It doesn't require any 'magic'. It doesn't require any verbose syntax. It solves pretty much all the problems. 1. You can no longer call functions as properties that were never intended to be (writeln = 4; goes away). 2. The "obj.prop(args)" ambiguity goes away. *Either* obj.prop is a normal method function and (args) are passed to it, *or* obj.prop has the "property" attribute, and (args) are passed to its result. Stuff like "obj.prop[i]" is the same way. 3. There is no naming ambiguity. 4. There are no case issues. 5. It provides useful semantic information to tools, IDEs, and reflection. 6. It's nonintrusive and self-documenting.

This gets my vote. Clean, elegant, works well, looks good.
Aug 01 2009
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-01 11:56:23 -0400, Jarrett Billingsley 
<jarrett.billingsley gmail.com> said:

 It's been mentioned before, and I'll mention it again: a simple
 'property' attribute that can be applied to any function.  No new
 syntax, no get/set/value 'magic' keywords, just 'property.'  Applying
 it to a function makes the compiler enforce the property syntax when
 using the functions.  Any function that doesn't have the property
 attribute - which should be most functions - can't be treated as one.
 It doesn't require any special support from the compiler beyond what
 it currently does.  It doesn't require any 'magic'.  It doesn't
 require any verbose syntax.  It solves pretty much all the problems.

That wasn't addressed to me, but since I started this thread, I feel I should answer. What problems does your proposal solve that aren't solved by a naming convention and the compiler following that convention to enable the property syntax? From what I see, you prefer adding a property keyword over a naming convention. That's fine, but I think otherwise. Let's compare them on a technical level using your checklist:
 1. You can no longer call functions as properties that were never
 intended to be (writeln = 4; goes away).

Same as with a get/set prefix, except that you can now explicitly call getSomething()/setSomething() if you want (a minor advantage in my opinion).
 2. The "obj.prop(args)" ambiguity goes away.  *Either* obj.prop is a
 normal method function and (args) are passed to it, *or* obj.prop has
 the "property" attribute, and (args) are passed to its result.  Stuff
 like "obj.prop[i]" is the same way.

Either obj.prop binds to a real function, or it isn't really there and the compiler maps it to getProp/setProp as needed. Same thing for "obj.prop[i]", which would be equivalent to "obj.getProp()[i]" if there is no "prop" member in "obj". So both proposals are as good in this respect.
 3. There is no naming ambiguity.

A set/get prefix removes pretty much all ambiguity too. I mean, the current syntax is "T transform()" and you can't know if transform is a noun or a verb. With my prefix it's "T getTransform()" which makes it pretty clear what it does. With yours it's "property T transform()" and it's pretty clear too.
 4. There are no case issues.

Indeed. +1 for your proposal.
 5. It provides useful semantic information to tools, IDEs, and reflection.

With a get/set prefix too you can get useful information about what you can set and get too. Sure you assume that get means get and set means set, just like you assume that everything using the property keyword is really meant to be a property with your proposal. (Both systems can be abused as easily, that's my point.)
 6. It's nonintrusive and self-documenting.

I'm not sure if you'd find a get/set prefix non-intrusive or not (I don't), but I find it as self-documenting as a property keyword. And to compensate that +1 for you above, I'd point out that there is an alternative with no case issue (get_thing/set_thing) and that your proposal requires a keyword. I have nothing against your proposal. I prefer the aestetics of mine and I believe they're both pretty equal on technical ground.
 The *only* technical issue I can come up with is if you had "property
 ref X foo()", where foo returned a reference to some value type.  Then
 you do "&obj.foo" - what does this get the address of?  To that end, I
 suggest that &obj.foo always gets the address of the member or method
 'foo' from object 'obj', and &(obj.foo) would get the address of the
 return value of obj.foo.  The extra parens in there say "really, I
 want you to evaluate the thing inside *first*".

Interesting. That's a problem that doesn't exist with with the naming convention proposal. About your idea, I find it confusing that (&something) and &(something) may not have the same meaning. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 01 2009
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-01 17:38:46 -0400, Jarrett Billingsley 
<jarrett.billingsley gmail.com> said:

 On Sat, Aug 1, 2009 at 4:01 PM, Michel Fortin<michel.fortin michelf.com> wrote:
 
 3. There is no naming ambiguity.

A set/get prefix removes pretty much all ambiguity too. I mean, the current syntax is "T transform()" and you can't know if transform is a noun or a verb. With my prefix it's "T getTransform()" which makes it pretty clear what it does. With yours it's "property T transform()" and it's pretty clear too.

class X { int foo; int getFoo() { return 5; } int blah() { return foo; /* um.. which? */ } }

Ok. There's two fronts on "ambiguity". You can have ambiguity in meaning, that's what I was talking about. By writing "setTransform()"/"getTransform()" you remove that ambiguity about "transform" being either a noun (property) or a verb (action). Having a keyword property does also removes that ambiguity. That's what I was talking about. Your example describe a syntaxic ambiguity when there's already a symbol named with the property name. There is a few way to solve that ambiguity: 1. Make it ambiguous (thus an error) to invoke foo at all. 2. Make foo, the variable, shadow the property. 3. Make the property shadow the variable. Number 3 is a bad idea because you have absolutely no way to access the field, even from inside the getter and setter. I'm not sure 2 is safe with multiple imported modules and with classes hierarchies. Number 1 is much restrictive, but you know when you're doing something fishy. - - - That said, a property keyword may also have some overloading problems to solve; it can't behave excaty as a function: class X { property void delegate(float) foo() { ... } property void foo(void delegate(float) f) { ... } void foo(float f) { ... } void blah() { foo(1.0); } // what is this? } You'll need a rule to forbid overloaded functions that mix property and non-property. That is, in class X and any derived class. Also, overload sets accross modules will need to be revised to become ambiguous when not all members are properties or non-properties. For instance, this would need to become ambiguous: module a; property void delegate(int) foo(); module b; int foo(float); module c; import a, b; unittest { foo(1); // which one? } This applies to a "getFoo()" syntax too.
 And to compensate that +1 for you above, I'd point out that there is an
 alternative with no case issue (get_thing/set_thing) and that your proposal
 requires a keyword.

Then let's introduce annotations and be done with it. No more pure, shared, __gshared, nothrow, and probably a whole slew of other silly attribute keywords.

To me, wether the keyword is "property" or a " property" annotation, I don't really care, both are fine with me. I still find "getFoo()"/"setFoo()" simpler and aesthetically better, but as I said before, the property keyword (be it a keyword or an annotation) is acceptable to me.
 About your idea, I find it confusing that (&something) and &(something) may
 not have the same meaning.

That's true. Then again, how often do you need to get the address of a returned ref value?

Every time you want to pass it to a C API. That said, perhaps I have a solution for that problem. The compiler could be smart about it, just like it already is when you take the address of an overloaded function: it could check if the variable you put the address into match the type of the property in addition to the type of the setter and the type of the getter. property ref int something(); property void something(int s); int delegate() getter = &something; // address of getter void delegate(int) setter = &something; // address of setter int* value = &something; // address of returned ref value Obviously, this doesn't work with auto, but that's a general problem with overloading, not something inehrent to properties. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 01 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Sat, 01 Aug 2009 11:56:23 -0400, Jarrett Billingsley  
<jarrett.billingsley gmail.com> wrote:
 1. You can no longer call functions as properties that were never
 intended to be (writeln = 4; goes away).

*sigh* writeln = 4 doesn't compile and hasn't for a while. It would be nice if the examples were valid code.
Aug 01 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 12:21 PM, Robert Jacques<sandford jhu.edu> wrote:
 On Sat, 01 Aug 2009 11:56:23 -0400, Jarrett Billingsley
 <jarrett.billingsley gmail.com> wrote:
 1. You can no longer call functions as properties that were never
 intended to be (writeln = 4; goes away).

*sigh* writeln = 4 doesn't compile and hasn't for a while. It would be nice if the examples were valid code.

I'm a D1 user. It compiles in D1, because writeln (or writefln) is defined as a normal non-templated function. Here, have this instead: void foo(int){} foo = 5;
Aug 01 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 1:38 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:

 Of course they're overridable. =A0They are *functions*.

Then why are you calling them properties? :o)

Stop deliberately misunderstanding me.
 So let me get this straight: the property attribute would be better
 technically, but let's not throw more keywords at it; so instead we sugg=


 attributes, but no, they don't have any useful purpose.

 WHAT.

I didn't say that.

Whatever. Have fun designing your own language, Andrei. Must be nice.
Aug 01 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 2:38 PM, Ary Borenszweig<ary esperanto.org.ar> wrote=
:
 Rainer Deyke escribi=F3:
 Ary Borenszweig wrote:
 The "property" just signals that the function is a property. But it's
 still a function and all of the previous rules that existed are still
 valid.

My problem with the 'property' syntax: Possibility 1: the property still acts like a function, so you can still do 'x.a()' when you mean 'x.a'. Possibility 2: the property does not act like a function, so you can no longer get a delegate to the property getter. Possibility 3: the property sometimes acts like a function and sometimes not, and you haven't defined the distinction.

None of those are correct. See Jarrett's post. property { =A0int x() { } =A0int x(int a) { } } auto a =3D x; // OK auto a =3D x(); // Wrong x =3D 2; // OK x(2); // Wrong

And furthermore, I mentioned that &obj.foo would always get the address of the member 'foo' from 'obj', even if 'foo' was a property. But hey, it's not like it matters anyway. We're pissing in the ocean.
Aug 01 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Aug 1, 2009 at 4:01 PM, Michel Fortin<michel.fortin michelf.com> wrote:

 3. There is no naming ambiguity.

A set/get prefix removes pretty much all ambiguity too. I mean, the current syntax is "T transform()" and you can't know if transform is a noun or a verb. With my prefix it's "T getTransform()" which makes it pretty clear what it does. With yours it's "property T transform()" and it's pretty clear too.

class X { int foo; int getFoo() { return 5; } int blah() { return foo; /* um.. which? */ } }
 And to compensate that +1 for you above, I'd point out that there is an
 alternative with no case issue (get_thing/set_thing) and that your proposal
 requires a keyword.

Then let's introduce annotations and be done with it. No more pure, shared, __gshared, nothrow, and probably a whole slew of other silly attribute keywords.
 About your idea, I find it confusing that (&something) and &(something) may
 not have the same meaning.

That's true. Then again, how often do you need to get the address of a returned ref value?
Aug 01 2009