www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Do we want functions to act as properties, or merely omit parens

reply Chad Joan <chadjoan gmail.com> writes:
Would everyone be able to agree to only use  property functions as 
properties?  This would still allow omittable parens as a way to make 
call-chaining and ufcs nicer.

The limitation this imposes is that
   void foo(int a) {...}
   void bar(int a, int b) {...}
cannot be called in this way:
   foo = 2;
   2.bar = 3;

As a consequence, everyone's favorite
   writeln = "lolwut";
does not compile.

What is still allowed:
   int foo() {...}
   void  property bar(int a) {...}
   ...
   int x = foo;
   bar = x;
   auto r = lets.chain!(q).some.stuff;

Although this seems like a distinction that's been discussed, I could 
never really tell if there was consensus on this.

Admittedly, I stopped following the " property needed or not needed?" 
discussion halfway through.

As someone who has taken a stab at doing semantic property rewriting, I 
think this is a limitation that could potentially help us in the long 
run.  It simplifies detection of properties: properties are only the 
things explicitly marked as such, and functions with omitted parens can 
follow a simpler codepath that the in-depth semantic rewrites can safely 
ignore.
Jan 28 2013
next sibling parent reply "F i L" <witte2008 gmail.com> writes:
why in the hell would you want:

     writeln = "lolwut";

to compile in the first place?
Jan 28 2013
next sibling parent reply Chad Joan <chadjoan gmail.com> writes:
On 01/28/2013 08:09 PM, F i L wrote:
 why in the hell would you want:

 writeln = "lolwut";

 to compile in the first place?
Dunno. But it does right now ;)
Jan 28 2013
parent reply "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 01:24:45 UTC, Chad Joan wrote:
 On 01/28/2013 08:09 PM, F i L wrote:
 why in the hell would you want:

 writeln = "lolwut";
But it does right now ;)
Joking here, but what about renaming writeln into cout and overloading the <<?
Jan 29 2013
parent "simendsjo" <simendsjo gmail.com> writes:
On Tuesday, 29 January 2013 at 08:05:25 UTC, eles wrote:
 On Tuesday, 29 January 2013 at 01:24:45 UTC, Chad Joan wrote:
 On 01/28/2013 08:09 PM, F i L wrote:
 why in the hell would you want:

 writeln = "lolwut";
But it does right now ;)
Joking here, but what about renaming writeln into cout and overloading the <<?
Great idea :) import std.stdio; struct COut { COut opBinary(string op, T)(T other) if(op == "<<") { write(other); return this; } } property COut cout() { return COut(); } void main() { cout << "cout" << " " << "rocks" << "\n"; }
Jan 29 2013
prev sibling parent reply "sclytrack" <sclytrack propertymethod.com> writes:
On Tuesday, 29 January 2013 at 01:09:17 UTC, F i L wrote:
 why in the hell would you want:

     writeln = "lolwut";

 to compile in the first place?
If you disallow this. You will have to invent something else than opDispatch. Something that serves them both. opPropMethodDispatch maybe.
Jan 28 2013
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-01-29 05:16, sclytrack wrote:

 If you disallow this. You will have to invent something else than
 opDispatch.
 Something that serves them both. opPropMethodDispatch maybe.
Why not allow to overload on property? -- /Jacob Carlborg
Jan 29 2013
prev sibling parent reply =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= <sludwig outerproduct.org> writes:
Am 29.01.2013 05:16, schrieb sclytrack:
 On Tuesday, 29 January 2013 at 01:09:17 UTC, F i L wrote:
 why in the hell would you want:

     writeln = "lolwut";

 to compile in the first place?
If you disallow this. You will have to invent something else than opDispatch. Something that serves them both. opPropMethodDispatch maybe.
template opDispatch(string name) { static if( isAProperty!name ){ property int opDispatch() { return 0; } } else { void opDispatch() {} } } or similar should work.
Jan 29 2013
parent reply "sclytrack" <sclytrack dynamic.com> writes:
On Tuesday, 29 January 2013 at 10:34:59 UTC, Sönke Ludwig wrote:
 Am 29.01.2013 05:16, schrieb sclytrack:
 On Tuesday, 29 January 2013 at 01:09:17 UTC, F i L wrote:
 why in the hell would you want:

     writeln = "lolwut";

 to compile in the first place?
If you disallow this. You will have to invent something else than opDispatch. Something that serves them both. opPropMethodDispatch maybe.
template opDispatch(string name) { static if( isAProperty!name ){ property int opDispatch() { return 0; } } else { void opDispatch() {} } } or similar should work.
I meant for dynamic D where you don't know if it is a property or a method at compile time. Where you don't know if the method even exists or not. Overloading on an annotation is just weird. Either something is annotated or not. Going to eat now.
Jan 29 2013
parent Chad Joan <chadjoan gmail.com> writes:
On 01/29/2013 06:03 AM, sclytrack wrote:
 On Tuesday, 29 January 2013 at 10:34:59 UTC, Sönke Ludwig wrote:
 Am 29.01.2013 05:16, schrieb sclytrack:
 On Tuesday, 29 January 2013 at 01:09:17 UTC, F i L wrote:
 why in the hell would you want:

 writeln = "lolwut";

 to compile in the first place?
If you disallow this. You will have to invent something else than opDispatch. Something that serves them both. opPropMethodDispatch maybe.
template opDispatch(string name) { static if( isAProperty!name ){ property int opDispatch() { return 0; } } else { void opDispatch() {} } } or similar should work.
I meant for dynamic D where you don't know if it is a property or a method at compile time. Where you don't know if the method even exists or not. Overloading on an annotation is just weird. Either something is annotated or not. Going to eat now.
I didn't think it was an overload. I also don't understand the bit about dynamic D, because the dispatch in opDispatch always occurs at compile-time. Any strings used as method names on a type with opDispatch must be known at compile-time. This is reasonably expressive enough that I wonder if you're doing other dynamic calculations behind that all. That template works, though I was also thinking about this natural use-case: import std.stdio; class Foo { void opDispatch(string name)(int arg) { writefln("%s(%s) called",name,arg); } property opDispatch(string name : "prop")(int arg) { writefln("prop = %s", arg); } } void main() { auto f = new Foo(); f.test(5); f.prop = 9; } // Writes: // test(5) called // prop = 9 This might be confusing to me because I'm not sure what your use case is. How are you generating your opDispatch functions currently where this becomes a problem?
Jan 29 2013
prev sibling next sibling parent reply "Craig Dillabaugh" <cdillaba cg.scs.carleton.ca> writes:
On Tuesday, 29 January 2013 at 00:56:41 UTC, Chad Joan wrote:
 snip

 The limitation this imposes is that
   void foo(int a) {...}
   void bar(int a, int b) {...}
 cannot be called in this way:
   foo = 2;
   2.bar = 3;

 snip
I have been following the properties discussion a bit and lack the experience to really comment on much. However, looking at your posting I couldn't help but ask one question. You state that not allowing at statement like: 2.bar = 3; is a 'limitation'. Was 'limitation' really the word you were looking for? I find such code rather baffling. Perhaps it has valuable uses somewhere, which is why I am asking. It sort of reminds me of Python where you can do something like: ' '.join( list_of_strings ) which is very cute and all, but the following, rather mundane function call would do a better job of conveying to the reader what is going on, using the same number of keystrokes: join( list_of_strings, ' ') Craig
Jan 28 2013
next sibling parent reply Chad Joan <chadjoan gmail.com> writes:
On 01/28/2013 08:59 PM, Craig Dillabaugh wrote:
 On Tuesday, 29 January 2013 at 00:56:41 UTC, Chad Joan wrote:
 snip

 The limitation this imposes is that
 void foo(int a) {...}
 void bar(int a, int b) {...}
 cannot be called in this way:
 foo = 2;
 2.bar = 3;

 snip
I have been following the properties discussion a bit and lack the experience to really comment on much. However, looking at your posting I couldn't help but ask one question. You state that not allowing at statement like: 2.bar = 3; is a 'limitation'. Was 'limitation' really the word you were looking for? I find such code rather baffling. Perhaps it has valuable uses somewhere, which is why I am asking. It sort of reminds me of Python where you can do something like: ' '.join( list_of_strings ) which is very cute and all, but the following, rather mundane function call would do a better job of conveying to the reader what is going on, using the same number of keystrokes: join( list_of_strings, ' ') Craig
I mean limitation in the mathematical sense. It's a combination of syntax elements that are valid in current D, but would no longer be valid if the D community were to desire a properties solution that includes this condition. If no one is harmed by this limitation, then it is still a "limitation", and also a /useful/ limitation.
Jan 28 2013
parent "Craig Dillabaugh" <cdillaba cg.scs.carleton.ca> writes:
On Tuesday, 29 January 2013 at 02:54:44 UTC, Chad Joan wrote:
 On 01/28/2013 08:59 PM, Craig Dillabaugh wrote:
 On Tuesday, 29 January 2013 at 00:56:41 UTC, Chad Joan wrote:
 snip

 The limitation this imposes is that
 void foo(int a) {...}
 void bar(int a, int b) {...}
 cannot be called in this way:
 foo = 2;
 2.bar = 3;

 snip
I have been following the properties discussion a bit and lack the experience to really comment on much. However, looking at your posting I couldn't help but ask one question. You state that not allowing at statement like: 2.bar = 3; is a 'limitation'. Was 'limitation' really the word you were looking for? I find such code rather baffling. Perhaps it has valuable uses somewhere, which is why I am asking. It sort of reminds me of Python where you can do something like: ' '.join( list_of_strings ) which is very cute and all, but the following, rather mundane function call would do a better job of conveying to the reader what is going on, using the same number of keystrokes: join( list_of_strings, ' ') Craig
I mean limitation in the mathematical sense. It's a combination of syntax elements that are valid in current D, but would no longer be valid if the D community were to desire a properties solution that includes this condition. If no one is harmed by this limitation, then it is still a "limitation", and also a /useful/ limitation.
Thanks. That is what I was hoping was the case. I was just curious if perhaps such obscure looking code enabled certain idioms that somehow made the language more powerful.
Jan 28 2013
prev sibling next sibling parent FG <home fgda.pl> writes:
On 2013-01-29 02:59, Craig Dillabaugh wrote:
 I find such code rather baffling. Perhaps it has valuable uses
 somewhere, which is why I am asking.

 It sort of reminds me of Python where you can do something like:

 ' '.join( list_of_strings )

 which is very cute and all, but the following, rather mundane
 function call would do a better job of conveying to the reader
 what is going on, using the same number of keystrokes:

 join( list_of_strings, ' ')
Thanks to D I no longer have problems with join in Python. :) Looking at ' '.join(aList) I now think of UFCS and see it as: join(' ', aList). Suddenly everything is clear. :)
Jan 29 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-01-29 02:59, Craig Dillabaugh wrote:

 It sort of reminds me of Python where you can do something like:

 ' '.join( list_of_strings )
That looks kind of backwards. I would go with: list_of_strings.join(' ') Which feels more natural. -- /Jacob Carlborg
Jan 29 2013
prev sibling next sibling parent reply "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 00:56:41 UTC, Chad Joan wrote:
 Would everyone be able to agree to only use  property functions 
 as properties?
I think property-ies should not be taken for functions... at least conceptually. I think the root reason why such confusion is the bad choice that D made in the beginning, to define properties with the same syntax as functions, while properties should be rather an extensions of the variable concept, not of the functions concept. For the programmer using a property, he should not even be aware that it is a function (or a property). He should think that it is a variable and that's all. linking the code (of both the getter and the setter) with the considered property. In D, this link is quite loose. Let me turn the table: why not thinking about the property as a variable that, optionally (start another UFCS/opt-parens discussion here...) accept the syntax: v(2); (besides the obvious v=2). This happens in C++ where you can define either int x= 3; either int x(3). More confusing?
Jan 29 2013
next sibling parent reply "jerro" <a a.com> writes:
 I think the root reason why such confusion is the bad choice 
 that D made in the beginning, to define properties with the 
 same syntax as functions, while properties should be rather an 
 extensions of the variable concept, not of the functions 
 concept.
Properties should only appear to be variables from the user's point of view. From the implementation point of view, they *are* functions. So the syntax for getting and setting property values should be the same as for variables, but for implementing them, it makes sense to use syntax that is close to the one used for functions. That way, you can avoid verbosity and the need to use Current implementation of properties in D is not perfect, but the only issue with the syntax for implementing them is that there isn't a clear distinction between setters and getters, which leads to some confusion with global properties in the presence of UFCS. But that can be solved by having property(get) and property(set) or getter and setter. No need to adopt the
Jan 29 2013
next sibling parent reply "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:
 to the one used for functions. That way, you can avoid 
 verbosity and the need to use implicit parameters
What do you eran from that? Sparing "value" as a reusable identifier? You define a getter at the top of the class, then finding a setter three screens lower and you finnaly learn that the property is not that "read-only"? I think the first step into better property definition/implementation/comprehension would be exactly that: to force the code of the getter and the code of the setter to stick together. Yes, exactly at the user of a property I was thinking. That user is also a programmer, but he does not do the implementation of the property, just using it. The confusion does not lie with that user, but it was sparked when the implementation decision was made, in the very heads of those who started implementing properties as just-another-function. This confusion propagates from the implementors to the user, as the (usage) syntax issues are issues for the user. It also does not help that, for the time being, the users of properties are also the implementors of properties. There is not much objectivity in this case.
Jan 29 2013
next sibling parent reply "jerro" <a a.com> writes:
 What do you eran from that? Sparing "value" as a reusable 
 identifier?
Not using a magic identifier, which makes the code clearer.
 You define a getter at the top of the class, then finding a 
 setter three screens lower and you finnaly learn that the 
 property is not that "read-only"?
Nothing is stopping you from keeping the getter and setter together. It also seems to me that this is something people would usually do, as you usually write one of those right before you write the other, and later inserting some other definition between them just feels wrong. How many times have you encountered this problem?
 I think the first step into better property 
 definition/implementation/comprehension would be exactly that: 
 to force the code of the getter and the code of the setter to 
 stick together.

 Yes, exactly at the user of a property I was thinking. That 
 user is also a programmer, but he does not do the 
 implementation of the property, just using it.

 The confusion does not lie with that user, but it was sparked 
 when the implementation decision was made, in the very heads of 
 those who started implementing properties as 
 just-another-function.

 This confusion propagates from the implementors to the user, as 
 the (usage) syntax issues are issues for the user.

 It also does not help that, for the time being, the users of 
 properties are also the implementors of properties. There is 
 not much objectivity in this case.
So you are assuming that having a special syntax for defining properties has some psychological effect on programmers that results in proper usage of properties, and that the lack of such syntax in D is the main reason for improper property usage. I disagree. I think that the main reason property is currently overused in D is that people were under the impression that paren-less calls will only be supported for property functions in the future. So if people wanted some of their functions to be callable without parens (and some people do want that), they actually had an incentive to make them property, even if they weren't logically properties.
Jan 29 2013
parent "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 12:18:56 UTC, jerro wrote:
 What do you eran from that? Sparing "value" as a reusable 
 identifier?
Not using a magic identifier, which makes the code clearer.
Yes. What about removing $ in array context? That makes it a very magic identifier. OK: use "$" instead of "value". It is magic already.
 Nothing is stopping you from keeping the getter and setter 
 together.
The problem is that nobody enforces you. Nobody is stopping you from writing corect code, I can swear that. Still, bugs exist. And in your code, too.
 So you are assuming that having a special syntax for defining 
 properties has some psychological effect on programmers that 
 results in proper usage of properties, and that the lack of 
 such syntax in D is the main reason for improper property usage.
I think it will make things clearer for them: a lot of debate was needed just to make clear that UFCS/optional_parens and property are orthogonal issues. Do you think that confusion in the beginning had nothing to do with the F meaning... FUNCTION?
 I disagree. I think that the main reason  property is currently 
 overused in D  is that people were under the impression that 
 paren-less  calls will only be supported for  property 
 functions in the future. So if people wanted some of their 
 functions to be callable without parens (and some people do 
 want that), they actually had an incentive to make them 
  property, even if they weren't logically properties.
You see: optional parens mean function, property means property. The confusion that you spot is exactly the confusion that is rooted into that mix of properties and functions.
Jan 29 2013
prev sibling parent reply Chad Joan <chadjoan gmail.com> writes:
On 01/29/2013 06:26 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:
 to the one used for functions. That way, you can avoid verbosity and
 the need to use implicit parameters
What do you eran from that? Sparing "value" as a reusable identifier? You define a getter at the top of the class, then finding a setter three screens lower and you finnaly learn that the property is not that "read-only"? I think the first step into better property definition/implementation/comprehension would be exactly that: to force the code of the getter and the code of the setter to stick together. Yes, exactly at the user of a property I was thinking. That user is also a programmer, but he does not do the implementation of the property, just using it. The confusion does not lie with that user, but it was sparked when the implementation decision was made, in the very heads of those who started implementing properties as just-another-function. This confusion propagates from the implementors to the user, as the (usage) syntax issues are issues for the user. It also does not help that, for the time being, the users of properties are also the implementors of properties. There is not much objectivity in this case.
property int foo { get { return m_foo; } set { m_foo = value; } } - They introduce an extra nesting level. - There is a possible nonsense error if someone places code outside of the get/set but inside the property scope. - You don't get to determine how the setter value is passed. ref? auto ref? const? - They use 4 keywords, whereas we can get away with 2 probably. - Things get uglier when you add D's function pure and const annotations to it. I think there are another disadvantage or two that Andrei mentioned before in a property discussion a couple years ago. He fairly well Semantically, they accomplish the same thing as D's properties: they get lowered into two methods, one getter and one setter. There has to be /some/ way to attach executable code to a symbol for this properties concept to work at all.
Jan 29 2013
parent reply "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 13:51:05 UTC, Chad Joan wrote:
 On 01/29/2013 06:26 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:
 to the one used for functions. That way, you can avoid 
 verbosity and
 the need to use implicit parameters
YRC.
 property int foo
 {
 	get
 	{
 		return m_foo;
 	}
 	
 	set
 	{
 		m_foo = value;
 	}
 }


 - They introduce an extra nesting level.
 - There is a possible nonsense error if someone places code 
 outside of the get/set but inside the property scope.
The compiler will scream at you. This is why it analyses the code, to make sure it understands it.
 - You don't get to determine how the setter value is passed.  
 ref? auto ref? const?
Frankly? Why you would care? You only write a.x=b. How it is b passed? It is the job of the compiler to pass b, not yours.
 - They use 4 keywords, whereas we can get away with 2 probably.
Yes. This is why brainfuck become no.1 language ever invented, because it uses very few keywords. And this is why Java never really took off, just because it introduces new keywords like extends and implements instead of our lovely :. Lovo of keywords changed the world...
 - Things get uglier when you add D's function pure and const 
 annotations to it.
*Everything* become uglier with that. Everything.
 Semantically, they accomplish the same thing as D's properties: 
 they get lowered into two methods, one getter and one setter.  
 There has to be /some/ way to attach executable code to a 
 symbol for this properties concept to work at all.
If they are the same, why they are different to the point that you love one but hate the other?
Jan 29 2013
parent reply Chad Joan <chadjoan gmail.com> writes:
On 01/29/2013 09:14 AM, eles wrote:
 On Tuesday, 29 January 2013 at 13:51:05 UTC, Chad Joan wrote:
 On 01/29/2013 06:26 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:
 to the one used for functions. That way, you can avoid verbosity and
 the need to use implicit parameters
YRC.
 property int foo
 {
 get
 {
 return m_foo;
 }

 set
 {
 m_foo = value;
 }
 }


 - They introduce an extra nesting level.
 - There is a possible nonsense error if someone places code outside of
 the get/set but inside the property scope.
The compiler will scream at you. This is why it analyses the code, to make sure it understands it.
My point is that this is another error that has to be coded into the compiler. Another error that can show up on your screen. Generally it is a better course to make it impossible for errors to happen at all.
 - You don't get to determine how the setter value is passed. ref? auto
 ref? const?
Frankly? Why you would care? You only write a.x=b. How it is b passed? It is the job of the compiler to pass b, not yours.
I do care. Whether things are const or not matters a lot. You wouldn't be able to write (foo.prop = "hi") if prop has a non-const parameter. Also, if the property type is some large struct, then I'll want to pass it as ref to avoid a huge copy overhead.
 - They use 4 keywords, whereas we can get away with 2 probably.
Yes. This is why brainfuck become no.1 language ever invented, because it uses very few keywords. And this is why Java never really took off, just because it introduces new keywords like extends and implements instead of our lovely :. Lovo of keywords changed the world...
 - Things get uglier when you add D's function pure and const
 annotations to it.
*Everything* become uglier with that. Everything.
 Semantically, they accomplish the same thing as D's properties: they
 get lowered into two methods, one getter and one setter. There has to
 be /some/ way to attach executable code to a symbol for this
 properties concept to work at all.
If they are the same, why they are different to the point that you love one but hate the other?
Semantics != Syntax "Semantically" is a really important qualifier in formal language discussion.
Jan 29 2013
next sibling parent "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 14:33:12 UTC, Chad Joan wrote:
 On 01/29/2013 09:14 AM, eles wrote:
 On Tuesday, 29 January 2013 at 13:51:05 UTC, Chad Joan wrote:
 On 01/29/2013 06:26 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:
 to the one used for functions. That way, you can avoid 
 verbosity and
 the need to use implicit parameters
I do care. Whether things are const or not matters a lot. You wouldn't be able to write (foo.prop = "hi") if prop has a non-const parameter.
So, with the current approach, if one forgets to write the non-const parameter, will very likely end up with a property that is context-sensitive... Surely, I have the feeling that functions are the simple thing, while properties are some new, more complicated language constructs, that were invented in order to overcome the limitations of those poor functions... At least now we have a strong reason why properties are needed in the language: just as every C/C++ program can be reduced to a for() loop, so every D program will be reduceable to a property... It is a matter to keep up with C++ after all.
Jan 29 2013
prev sibling parent "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 14:33:12 UTC, Chad Joan wrote:
 On 01/29/2013 09:14 AM, eles wrote:
 On Tuesday, 29 January 2013 at 13:51:05 UTC, Chad Joan wrote:
 On 01/29/2013 06:26 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:
 to the one used for functions. That way, you can avoid 
 verbosity and
 the need to use implicit parameters
Semantics != Syntax "Semantically" is a really important qualifier in formal language discussion.
Syntax is a very subjective thing (remember that writeln = "hello"?). Concepts are important to be constructed well. I think (well, subjectively), that properties are closer, conceptually, to variables than to functions. At least, they should be.
Jan 29 2013
prev sibling parent reply "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:

And there is another problem with the "superior" D approach: a typing mistake in the name of a property might let you not with one property that is r/w, but with two properties to which one is r/o and the other is w/o. More, those functions might be placed several screens far one from the other. Even more, defining the properties as (regular) functions makes it very difficult to teach a programmer: "in this body of code you should restrain yourself from doing certain things", because he already feels that inside a function he shoiuld have a lot of freedom. It would have been easier to say: "you know, property is like a variable, but you can also add there *some* instructions (ie: range checking, database interrogation, cache and so on)".
Jan 29 2013
next sibling parent reply "jerro" <a a.com> writes:
 And there is another problem with the "superior" D approach: a 
 typing mistake in the name of a property might let you not with 
 one property that is r/w, but with two properties to which one 
 is r/o and the other is w/o.
A bug like this will be found as soon as someone writes a test for that property or writes some code that uses it. And once it is found, it is trivial to fix. If the code was not tested at all, it is bound to contain other bugs anyway and some of those will be much harder to find and to fix.
Jan 29 2013
parent "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 12:24:18 UTC, jerro wrote:
 A bug like this will be found as soon as someone writes a test 
 for that property or writes some code that uses it. And once it 
 is found, it is trivial to fix. If the code was not tested at 
 all, it is bound to contain other bugs anyway and some of those 
 will be much harder to find and to fix.
except that someone would write the getter, then write the tests for the getter. several years latter, another programmer writes the setter, and then the tests for the setter. both the tests for the setter and for the getter work (and, through some hasard, even read/write tests would work, if anybody care to write). then you put that class into production code and the plane crashes.
Jan 29 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 1/29/13 6:33 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:

And there is another problem with the "superior" D approach: a typing mistake in the name of a property might let you not with one property that is r/w, but with two properties to which one is r/o and the other is w/o. More, those functions might be placed several screens far one from the other.
I agree this is an issue. I think it's good language design to avoid "long-distance influence" of one declaration against another. This is a strong argument for keeping property for write properties. Andrei
Jan 29 2013
parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 29 Jan 2013 09:38:57 -0600, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 On 1/29/13 6:33 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:

And there is another problem with the "superior" D approach: a typing mistake in the name of a property might let you not with one property that is r/w, but with two properties to which one is r/o and the other is w/o. More, those functions might be placed several screens far one from the other.
I agree this is an issue. I think it's good language design to avoid "long-distance influence" of one declaration against another. This is a strong argument for keeping property for write properties. Andrei
How so? The op's argument is against having separate function declarations ala D, and for a joint getter/setter syntax. i.e. foo { get; set; } // vs int foo() { return 5; } void fou(int x) {} Because, as illustrated above, the two function names might accidentally be different. As the functions, like all overloads, should be 1 code-fold apart, the actual severity of the bug is the same as accidentally changing the name of an overloaded function during initial coding or during a refactor. Which is neither for nor against property, but advocating new syntax and keywords for defining properties.
Jan 29 2013
parent "eles" <eles eles.com> writes:
On Wednesday, 30 January 2013 at 01:59:52 UTC, Robert Jacques 
wrote:
 On Tue, 29 Jan 2013 09:38:57 -0600, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 On 1/29/13 6:33 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:13:19 UTC, jerro wrote:
How so? The op's argument is against having separate function declarations ala D, and for a joint getter/setter syntax. i.e. foo { get; set; } // vs int foo() { return 5; } void fou(int x) {} Because, as illustrated above, the two function names might accidentally be different. As the functions, like all overloads, should be 1 code-fold apart, the actual severity of the bug is the same as accidentally changing the name of an overloaded function during initial coding or during a refactor. Which is neither for nor against property, but advocating new syntax and keywords for defining properties.
He means that in the context where you cannot have write-only properties. So, you have to have at least the getter. Imposing property on the setter means that a getter with the same name is needed. This lowers the probability of a typo, since a property fou() will be caught by the compiler as having no getter counterpart. Sure enough, this does not prevent having two getters for foo and fou properties, then mistakenly writing the setter for fou while intenfing to write the setter for foo.
Jan 30 2013
prev sibling parent reply FG <home fgda.pl> writes:
On 2013-01-29 09:03, eles wrote:
 Let me turn the table: why not thinking about the property as a variable that,
 optionally (start another UFCS/opt-parens discussion here...) accept the
syntax:

 v(2);
It is a bit confusing because if it were methods/functions you'd typically have "getV()" and "setV(2)" which show what is being done here. "v(2)" on the other hand doesn't make it clear whether it will set the value or read it. After all "2" might be some flag/index/anything used to specify the return value and it still won't make "v(int)" a setter. In the end one would have to look into the docs to see what "v" does. This is unnecessary if you either tell in the function name what will be performed or use the property like any normal variable. Therefore when using properties I would rather just see "v" and "v = 2" (and also expect "w = v = 2" to work). Assuming that "w" is a plain int variable, I wouldn't expect to see v(2) anywhere outside initialization, just like I would not expect to see w(2).
Jan 29 2013
parent reply "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 11:36:22 UTC, FG wrote:
 On 2013-01-29 09:03, eles wrote:

 It is a bit confusing
I know. It was an alternative way of thinking, displayed just to show how weird things may become. I also fine writeln = "hello" very confusing. Is that a variable assignment, btw? What do you think?
Jan 29 2013
next sibling parent FG <home fgda.pl> writes:
On 2013-01-29 13:13, eles wrote:
 I also find

 writeln = "hello"

 very confusing. Is that a variable assignment, btw? What do you think?
To me this is just a lousy party trick... pulling a rabbit out of the hat. ;) Makes absolutely no sense, because writeln doesn't store "hello" in its state - there is no way to read it. Maybe it's a limited mindset, but to me properties should be read-only or read-write, but not write-only. On the other hand, if it was a hypothetical property (let's call it "lastDebugMessage"), that stores and returns the string, while also printing it as a side-effect, then it could be acceptable (although this particular example is of limited practical value).
Jan 29 2013
prev sibling parent reply Chad Joan <chadjoan gmail.com> writes:
On 01/29/2013 07:13 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:36:22 UTC, FG wrote:
 On 2013-01-29 09:03, eles wrote:

 It is a bit confusing
I know. It was an alternative way of thinking, displayed just to show how weird things may become. I also fine writeln = "hello" very confusing. Is that a variable assignment, btw? What do you think?
I don't think anyone likes it. What I'm trying to accomplish with my thread is find a way to remove such corner-cases without also removing other things that people care about, like omittable parens on call-chains.
Jan 29 2013
parent reply "eles" <eles eles.com> writes:
On Tuesday, 29 January 2013 at 13:52:27 UTC, Chad Joan wrote:
 On 01/29/2013 07:13 AM, eles wrote:
 On Tuesday, 29 January 2013 at 11:36:22 UTC, FG wrote:
 On 2013-01-29 09:03, eles wrote:
What I'm trying to accomplish with my thread is find a way to remove such corner-cases without also removing other things that people care about, like omittable parens on call-chains.
well, make those parens omittable (I think it is a molima: everybody seems to have fallen in love with that optional parens) only if the function name is followed by a dot. This will avoid such ugly things as: a.writeln; except for properties ( property will enforce this syntax, even if not followed by a dot).
Jan 29 2013
parent FG <home fgda.pl> writes:
On 2013-01-29 15:00, eles wrote:
 well, make those parens omittableonly if the function name is
 followed by a dot.
This is a sound idea for typical cases: typeof(foo); // works, x = a.chain.of.operations(); // looks good and () are informative. Only the problem with functions returning callable objects remains: write(foo()()); // ugly but explicit and we know what happens, foo().write(); // is it the phobos write or a write method // of the object returned by foo?
Jan 29 2013
prev sibling parent reply "Wyatt" <wyatt.epp gmail.com> writes:
On Tuesday, 29 January 2013 at 00:56:41 UTC, Chad Joan wrote:
 Would everyone be able to agree to only use  property functions 
 as properties?  This would still allow omittable parens as a 
 way to make call-chaining and ufcs nicer.
I've been thinking and, while it may just be a side effect of my code style or my own inexperience, I honestly can't think of a situation where I'd want I'd want to use a non- property function as an lvalue as described here.
 The limitation this imposes is that
   void foo(int a) {...}
   void bar(int a, int b) {...}
 cannot be called in this way:
   foo = 2;
   2.bar = 3;

 As a consequence, everyone's favorite
   writeln = "lolwut";
 does not compile.
Do people really do this with any degree of frequency? None of the examples I've seen read well to me, and readability of code is an important consideration when we need to represent semantic meaning with syntactic saccharides.
Jan 29 2013
parent reply "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
My opinion is to allow calling a function without parentheses 
only in UFCS (properties must be called without). Is that so hard 
to implement?
Jan 29 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 01/29/2013 08:36 PM, Minas Mina wrote:
 My opinion is to allow calling a function without parentheses only in
 UFCS (properties must be called without). Is that so hard to implement?
Implementation complexity is not too relevant. (But all proposals so far are easy to implement.)
Jan 29 2013
prev sibling parent "Michael" <pr m1xa.com> writes:
On Tuesday, 29 January 2013 at 19:36:50 UTC, Minas Mina wrote:
 My opinion is to allow calling a function without parentheses 
 only in UFCS (properties must be called without). Is that so 
 hard to implement?
+1, and workaround: property I Do(alias fun, I)(I o) { return o is null ? null : (fun(o), o); } foreach(p; persons) p.Do!(a => a.address.cityName.write()); and add -property option to compiler args.
Jan 29 2013