digitalmars.D - Property rewriting; I feel it's important. Is there still time?
- Chad J (66/66) Mar 09 2010 I speak of the property rewriting where an expression like
- retard (53/92) Mar 10 2010 This is so unbelievable. I knew the property stuff was being redesigned
- Andrei Alexandrescu (3/19) Mar 10 2010 I am having difficulty understanding what you are trying to convey.
- retard (11/37) Mar 10 2010 People very rarely find any issues worth complaining in the property
- Andrei Alexandrescu (29/62) Mar 10 2010 Absolutely. A good way to go about that is to raise the issue herein and...
- Andrei Alexandrescu (30/57) Mar 10 2010 This particular example has a number of issues. First off you need to
- bearophile (18/20) Mar 10 2010 I didn't know that. So I have tried this code:
- =?ISO-8859-1?Q?Pelle_M=E5nsson?= (3/23) Mar 10 2010 May we wish for a better error message in this case?
- Andrei Alexandrescu (3/23) Mar 10 2010 That's a bug worth submitting.
- bearophile (6/7) Mar 10 2010 OK:
- Andrei Alexandrescu (4/11) Mar 13 2010 BTW I noticed that you have recently submitted a great deal of bugs and
- Andrei Alexandrescu (5/26) Mar 10 2010 The latter should be:
- Ellery Newcomer (4/16) Mar 10 2010 no
- Andrei Alexandrescu (8/29) Mar 10 2010 Not sure I understand the question. The statement you mention would end
- Ellery Newcomer (2/35) Mar 10 2010 oop. nevermind. missed the void context part.
- Chad J (60/139) Mar 10 2010 Right. This one made itself easy to notice because if you either return
- Andrei Alexandrescu (7/34) Mar 11 2010 Yah, ideally both options should be available.
- Chad J (9/34) Mar 11 2010 Oh.
- bearophile (4/5) Mar 10 2010 Isn't it better to use the compiler to run the functions at compile time...
- Andrei Alexandrescu (5/13) Mar 10 2010 Staged compilation is an active research topic and many approaches could...
- Steven Schveighoffer (14/20) Mar 10 2010 I think this is fine as long as we don't take it to the extreme. That i...
- =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= (3/15) Mar 10 2010 Why would you not want that? That's exactly what should happen! Why not?...
- Steven Schveighoffer (27/48) Mar 11 2010 Hm... on second thought you are right. I meant to say something like th...
- Steven Schveighoffer (46/67) Mar 11 2010 BTW, C# doesn't do this:
- retard (4/74) Mar 11 2010 I hope that cannot be used as an argument against the feature. Scala
- =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= (3/5) Mar 12 2010 I still think D should, it makes little sense not to. What is gained
- Steven Schveighoffer (12/17) Mar 12 2010 It has been pointed out that C#'s properties are "right" after 4 years o...
I speak of the property rewriting where an expression like foo.prop++; is rewritten as auto t = foo.prop(); t++; foo.prop(t); So, Walter or Andrei or someone on the planning behind the scenes, please lend me your thoughts: How much time is left to make this sort of thing happen? If a working patch for this showed up, would it have a reasonable chance of acceptance at this point? I really want to make this happen, even if I have to pay someone to do it or finish it off. It's very close but I have almost nil free time for this stuff. Note that I have made it work and seen it in action. There'd be a patch two months ago if I hadn't decided to rebel against the way DMD did things*. Now I'll try and remind you why this patch is important: - I see no other way to make properties behave like lvalues in an elegant manner. Explicit property syntax does not help this. This is quite a semantics problem, and the syntax is completely orthogonal. - Having property rewrites allows the special case for "array.length += foo;" to be removed. Property rewriting is the more general solution that will work for all properties and in arbitrary expressions. - By treating opIndex and opIndexAssign as properties then that pair alone will make cases like "a[i]++;" work correctly without the need for opIndexUnary overloads. Also "a[i] += foo" will work too, as well as anything else you haven't thought of yet. - It has implications for purity. We may want to figure this out before its too late. Consider "foo.prop + bar;", where prop returns a struct with opBinary!("+") defined. It ends up being "foo.prop.opAdd(bar)". In general this is "foo.property.someFunction(args...)". In the general case you want it to call the setter function for the property so that any changes in state get propagated back to foo, as we would expect from an lvalue. If there is no setter, it's an error. However, in the (usual) case of opAdd, this is an unnecessary restriction since opAdd is likely pure and just returns a value -- there is no need to require foo to have a setter. It makes sense to me to allow the purity of member functions to determine whether or not any parent property needs its setter called. Alternatively we could just make member function calls not count as side effects for properties. That would be more dangerous though, because sometimes they ARE side effects. Things like += and -= are not as troubling because they are ALWAYS side effects, so we know what to do with them. I want +=, -=, ++, etc. to be covered even if this purity issue is completely ignored. * So I made it work. Just not well enough for production quality, unfortunately. The problem had nothing to do with the rewrite being difficult or impossible to do. Instead, the problem was me rebelling against the way DMD does things, followed by failing on rare instances of valid code. Calling Expression->semantic() twice on the same expression will do that.** This was all a little over two months ago, back when I was still unemployed. I've hardly touched it since then. ** If you're in the know, you might wonder why I would do a fool thing like call Expression->semantic() twice on the same expression. When I originally wrote the function for doing this rewrite, I wrote it to climb the expression tree with recursive calls. So I tried to keep that quality. I'd let semantic run, then I'd recursive over the tree, then run semantic again. I had an idea in mind to optimize away the second pass for expressions devoid of properties, or to even minimize the scanning to only the branches that had both side effects and properties. I was hoping this would at least make it work. But it doesn't. What I need to do then is rewrite my recursive function for doing the rewrite into a flat and non-recursive function that tracks its state using some combination of variables in Scope and variables in Expression. I'd be done already if I had just written it that way in the first place.
Mar 09 2010
Tue, 09 Mar 2010 22:48:08 -0500, Chad J wrote:I speak of the property rewriting where an expression like foo.prop++; is rewritten as auto t = foo.prop(); t++; foo.prop(t); So, Walter or Andrei or someone on the planning behind the scenes, please lend me your thoughts: How much time is left to make this sort of thing happen? If a working patch for this showed up, would it have a reasonable chance of acceptance at this point? I really want to make this happen, even if I have to pay someone to do it or finish it off. It's very close but I have almost nil free time for this stuff. Note that I have made it work and seen it in action. There'd be a patch two months ago if I hadn't decided to rebel against the way DMD did things*. Now I'll try and remind you why this patch is important: - I see no other way to make properties behave like lvalues in an elegant manner. Explicit property syntax does not help this. This is quite a semantics problem, and the syntax is completely orthogonal. - Having property rewrites allows the special case for "array.length += foo;" to be removed. Property rewriting is the more general solution that will work for all properties and in arbitrary expressions. - By treating opIndex and opIndexAssign as properties then that pair alone will make cases like "a[i]++;" work correctly without the need for opIndexUnary overloads. Also "a[i] += foo" will work too, as well as anything else you haven't thought of yet.This is so unbelievable. I knew the property stuff was being redesigned since there was so much talk in the ng some time ago. But even now, why on earth doesn't it work like it should. Is it so hard to copy/steal the good ideas from the better languages. Guess how C#/Scala solved this - I bet having a PhD helps getting things right the first time.. Scala: ------ object foo { def a = { println("getter returns 42"); 42 } def a_=(b:Int) = println("setter sets " + b) } scala> foo.a += 3 getter returns 42 setter sets 45 C#: --- using System; class Hello { public int id { get { Console.WriteLine ("getter returns 42"); return 42; } set { Console.WriteLine ("setter sets " + value); } } static void Main() { Hello h = new Hello(); h.id += 2; } } D: -- struct Foo { property int data() { return m_data; } // read property property int data(int value) { return m_data = value; } // write property private: int m_data; } void main() { Foo f; f.data += 3; } test.d(13): Error: 'f.data' is not a scalar, it is a property int() test.d(13): Error: incompatible types for ((f.data) += (3)): ' property int()' and 'int'
Mar 10 2010
On 03/10/2010 04:38 AM, retard wrote:Wed, 10 Mar 2010 10:05:03 +0000, retard wrote:I am having difficulty understanding what you are trying to convey. AndreiThis is so unbelievable. I knew the property stuff was being redesigned since there was so much talk in the ng some time ago. But even now, why on earth doesn't it work like it should. Is it so hard to copy/steal the good ideas from the better languages. Guess how C#/Scala solved this - I bet having a PhD helps getting things right the first time..Heh, after noticing the thread name "D hates to be dynamic linked" I should have probably renamed this thread with a funnier name such as "D stubbornly refuses to learn from mistakes and follow the principles of good language design". It took C# 4 years to get properties right. That period also included finishing a complete language specification document, totalling almost 500 pages. The property feature wasn't present in Pizza (2002), but Scala (2004 ->) had it. It was taken D 11 years to fail again and again miserably.
Mar 10 2010
Wed, 10 Mar 2010 08:53:57 -0600, Andrei Alexandrescu wrote:On 03/10/2010 04:38 AM, retard wrote:People very rarely find any issues worth complaining in the property system implementations of those languages. I also forgot to mention Object Pascal. Does this mean that C#/Scala/Pascal users are just complaining less or are their property systems just better? When a new system is adopted by D, does anyone really analyze the large body of existing work done on the field. We don't live in a dark and closed barrel, we can learn from others and try to avoid common problems. e.g. to me aWed, 10 Mar 2010 10:05:03 +0000, retard wrote:I am having difficulty understanding what you are trying to convey. AndreiThis is so unbelievable. I knew the property stuff was being redesigned since there was so much talk in the ng some time ago. But even now, why on earth doesn't it work like it should. Is it so hard to copy/steal the good ideas from the better languages. Guess how C#/Scala solved this - I bet having a PhD helps getting things right the first time..Heh, after noticing the thread name "D hates to be dynamic linked" I should have probably renamed this thread with a funnier name such as "D stubbornly refuses to learn from mistakes and follow the principles of good language design". It took C# 4 years to get properties right. That period also included finishing a complete language specification document, totalling almost 500 pages. The property feature wasn't present in Pizza (2002), but Scala (2004 ->) had it. It was taken D 11 years to fail again and again miserably.object.field += something;/is/ a rather fundamental part of any property system. It's really surprising that it still doesn't work..
Mar 10 2010
On 03/10/2010 09:12 AM, retard wrote:Wed, 10 Mar 2010 08:53:57 -0600, Andrei Alexandrescu wrote:Absolutely. A good way to go about that is to raise the issue herein and in bugzilla and also at best contribute patches that implement the improvements. There are some ways to go about improving things that are scraping the bottoms of some dubious barrels, and almost guaranteed to do more harm than good (primarily by making the perpetrator look like a fool). Latching on an obvious troll to make a point comes to mind. Also, I have difficulty understanding the concept of attempting to make Walter bad for not having a PhD, while at the same time relying on anonymity to cover insecurity about one's own achievements. One other thing that comes to mind is oscillating between being reasonable, then insulting, then apologetic, and then rinse lather and repeat. The logic is difficult to follow. Why bother apologizing if reenactment is a given? Getting to the topic at hand, there are two sides to the coin. D got right several things that other language authors are still scratching their heads about, such as proper integration of immutability with mutability, an expressive generics system, lightweight concepts, integration of interpretation with compilation, value range propagation in integral expressions, and I dare say concurrency. (I remember an interview with Hejlsberg and a colleague (Bentley?) in which he said they're having major headaches about modeling immutable data.) That doesn't make the authors of those languages incult or boneheaded. A language is a large ecosystem that makes it rather difficult to choose what to get busy with at any given time. Generalizing from one awkwardness (I agree that properties could receive more attention) to the entire language and even the author is not something anyone should be proud of. AndreiOn 03/10/2010 04:38 AM, retard wrote:People very rarely find any issues worth complaining in the property system implementations of those languages. I also forgot to mention Object Pascal. Does this mean that C#/Scala/Pascal users are just complaining less or are their property systems just better? When a new system is adopted by D, does anyone really analyze the large body of existing work done on the field. We don't live in a dark and closed barrel, we can learn from others and try to avoid common problems.Wed, 10 Mar 2010 10:05:03 +0000, retard wrote:I am having difficulty understanding what you are trying to convey. AndreiThis is so unbelievable. I knew the property stuff was being redesigned since there was so much talk in the ng some time ago. But even now, why on earth doesn't it work like it should. Is it so hard to copy/steal the good ideas from the better languages. Guess how C#/Scala solved this - I bet having a PhD helps getting things right the first time..Heh, after noticing the thread name "D hates to be dynamic linked" I should have probably renamed this thread with a funnier name such as "D stubbornly refuses to learn from mistakes and follow the principles of good language design". It took C# 4 years to get properties right. That period also included finishing a complete language specification document, totalling almost 500 pages. The property feature wasn't present in Pizza (2002), but Scala (2004 ->) had it. It was taken D 11 years to fail again and again miserably.
Mar 10 2010
On 03/09/2010 09:48 PM, Chad J wrote:I speak of the property rewriting where an expression like foo.prop++; is rewritten as auto t = foo.prop(); t++; foo.prop(t);This particular example has a number of issues. First off you need to rewrite expressions, not statements. Consider: auto x = foo.prop++; You'd need to assign to x the old value of foo.prop. So one correct rewrite is foo.prop++ into {auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}() within an rvalue context, and into: {auto t = foo.prop; ++t; foo.prop = t; return t;}() within a void context. I'm pointing out that things may not always be very simple, but generally it's easy to figure out the proper rewrites if attention is given to detail.So, Walter or Andrei or someone on the planning behind the scenes, please lend me your thoughts: How much time is left to make this sort of thing happen? If a working patch for this showed up, would it have a reasonable chance of acceptance at this point?The idea is sensible and is already in effect for the ".length" property of arrays.I really want to make this happen, even if I have to pay someone to do it or finish it off. It's very close but I have almost nil free time for this stuff. Note that I have made it work and seen it in action. There'd be a patch two months ago if I hadn't decided to rebel against the way DMD did things*.Probably offering payment wouldn't be much of an enticement, but lobbying reasonable ideas here is a good way to go.Now I'll try and remind you why this patch is important: - I see no other way to make properties behave like lvalues in an elegant manner. Explicit property syntax does not help this. This is quite a semantics problem, and the syntax is completely orthogonal.Good point.- Having property rewrites allows the special case for "array.length += foo;" to be removed. Property rewriting is the more general solution that will work for all properties and in arbitrary expressions.Agreed. By the way, I'm a huge fan of lowering; I think they are great for defining semantics in a principled way without a large language core. In recent times Walter has increasingly relied on lowerings and mentioned to me that the code savings in the compiler have been considerable.- By treating opIndex and opIndexAssign as properties then that pair alone will make cases like "a[i]++;" work correctly without the need for opIndexUnary overloads. Also "a[i] += foo" will work too, as well as anything else you haven't thought of yet.Well operator overloading handles indexing differently, and arguably better than in your proposal. Ideally we'd define operators on properties in a manner similar to the way indexing works in the new operator overloading scheme. I'll talk to Walter about that. Andrei
Mar 10 2010
Andrei Alexandrescu:The idea is sensible and is already in effect for the ".length" property of arrays.I didn't know that. So I have tried this code: void main() { int[] a; a.length++; a.length--; } The compiler shows the following errors, is this correct? test1.d(3): Error: a.length is not an lvalue test1.d(4): Error: a.length is not an lvalue So I have tried this, and this compiles: void main() { int[] a; ++a.length; --a.length; } Bye, bearophile
Mar 10 2010
On 03/10/2010 04:23 PM, bearophile wrote:Andrei Alexandrescu:May we wish for a better error message in this case? Anyway, I have always used += 1.The idea is sensible and is already in effect for the ".length" property of arrays.I didn't know that. So I have tried this code: void main() { int[] a; a.length++; a.length--; } The compiler shows the following errors, is this correct? test1.d(3): Error: a.length is not an lvalue test1.d(4): Error: a.length is not an lvalue So I have tried this, and this compiles: void main() { int[] a; ++a.length; --a.length; } Bye, bearophile
Mar 10 2010
On 03/10/2010 09:23 AM, bearophile wrote:Andrei Alexandrescu:That's a bug worth submitting. AndreiThe idea is sensible and is already in effect for the ".length" property of arrays.I didn't know that. So I have tried this code: void main() { int[] a; a.length++; a.length--; } The compiler shows the following errors, is this correct? test1.d(3): Error: a.length is not an lvalue test1.d(4): Error: a.length is not an lvalue So I have tried this, and this compiles: void main() { int[] a; ++a.length; --a.length; } Bye, bearophile
Mar 10 2010
Andrei Alexandrescu:That's a bug worth submitting.OK: http://d.puremagic.com/issues/show_bug.cgi?id=3927 (I have not started fixing bugs) Bye, bearophile
Mar 10 2010
On 03/10/2010 12:14 PM, bearophile wrote:Andrei Alexandrescu:BTW I noticed that you have recently submitted a great deal of bugs and good suggestions to bugzilla. Thanks! AndreiThat's a bug worth submitting.OK: http://d.puremagic.com/issues/show_bug.cgi?id=3927 (I have not started fixing bugs) Bye, bearophile
Mar 13 2010
On 03/10/2010 08:42 AM, Andrei Alexandrescu wrote:On 03/09/2010 09:48 PM, Chad J wrote:The latter should be: {auto t = foo.prop; ++t; foo.prop = t;}() because there's no need to return a value. AndreiI speak of the property rewriting where an expression like foo.prop++; is rewritten as auto t = foo.prop(); t++; foo.prop(t);This particular example has a number of issues. First off you need to rewrite expressions, not statements. Consider: auto x = foo.prop++; You'd need to assign to x the old value of foo.prop. So one correct rewrite is foo.prop++ into {auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}() within an rvalue context, and into: {auto t = foo.prop; ++t; foo.prop = t; return t;}() within a void context.
Mar 10 2010
On 03/10/2010 10:48 AM, Andrei Alexandrescu wrote:On 03/10/2010 08:42 AM, Andrei Alexandrescu wrote:no auto a = foo.prop++; ?{auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}() within an rvalue context, and into: {auto t = foo.prop; ++t; foo.prop = t; return t;}() within a void context.The latter should be: {auto t = foo.prop; ++t; foo.prop = t;}() because there's no need to return a value. Andrei
Mar 10 2010
On 03/10/2010 11:05 AM, Ellery Newcomer wrote:On 03/10/2010 10:48 AM, Andrei Alexandrescu wrote:Not sure I understand the question. The statement you mention would end up lowered to: auto a = {auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}(); which does what the user would expect. (Lowering is conceptual, e.g. inline code or an intrinsic named function could be used.) AndreiOn 03/10/2010 08:42 AM, Andrei Alexandrescu wrote:no auto a = foo.prop++; ?{auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}() within an rvalue context, and into: {auto t = foo.prop; ++t; foo.prop = t; return t;}() within a void context.The latter should be: {auto t = foo.prop; ++t; foo.prop = t;}() because there's no need to return a value. Andrei
Mar 10 2010
On 03/10/2010 11:10 AM, Andrei Alexandrescu wrote:On 03/10/2010 11:05 AM, Ellery Newcomer wrote:oop. nevermind. missed the void context part.On 03/10/2010 10:48 AM, Andrei Alexandrescu wrote:Not sure I understand the question. The statement you mention would end up lowered to: auto a = {auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}(); which does what the user would expect. (Lowering is conceptual, e.g. inline code or an intrinsic named function could be used.) AndreiOn 03/10/2010 08:42 AM, Andrei Alexandrescu wrote:no auto a = foo.prop++; ?{auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}() within an rvalue context, and into: {auto t = foo.prop; ++t; foo.prop = t; return t;}() within a void context.The latter should be: {auto t = foo.prop; ++t; foo.prop = t;}() because there's no need to return a value. Andrei
Mar 10 2010
Andrei Alexandrescu wrote:On 03/09/2010 09:48 PM, Chad J wrote:Right. This one made itself easy to notice because if you either return a value in a void context (ex: expression statements) or fail to return in a non-void context (ex: conditions for if/for/while statements and the like) then further execution of semantic analysis will error. What I end up doing is generating a bunch of comma expressions that hold the rewritten property expression. So my rewrite for "auto x = foo.prop++;" actually looks like this: auto x = (auto t = foo.prop, (auto t1 = t++, (foo.prop = t, t1))); It's illegal D code, but only because of a check (in Expression->semantic() somewhere IIRC) that prevents declaration expressions from appearing in arbitrary places. Once you're past that check you can put them there and the backend knows what to do with them. I stick t1 in there at the end to make the comma expression evaluate to the value of t1 at the end of the calculations. If it's a void context, I don't stick t1 in there at the end, because if I did then it would complain about having no side-effects.I speak of the property rewriting where an expression like foo.prop++; is rewritten as auto t = foo.prop(); t++; foo.prop(t);This particular example has a number of issues. First off you need to rewrite expressions, not statements. Consider: auto x = foo.prop++; You'd need to assign to x the old value of foo.prop. So one correct rewrite is foo.prop++ into {auto t = foo.prop; auto t1 = t; ++t1; foo.prop = t1; return t;}() within an rvalue context, and into: {auto t = foo.prop; ++t; foo.prop = t; return t;}() within a void context. I'm pointing out that things may not always be very simple, but generally it's easy to figure out the proper rewrites if attention is given to detail.I figure it might give an edge of motivation, especially to some of the talented college students around here. I would have probably done this kind of thing in college if the opportunity had popped up. I think Spring break is about here too.So, Walter or Andrei or someone on the planning behind the scenes, please lend me your thoughts: How much time is left to make this sort of thing happen? If a working patch for this showed up, would it have a reasonable chance of acceptance at this point?The idea is sensible and is already in effect for the ".length" property of arrays.I really want to make this happen, even if I have to pay someone to do it or finish it off. It's very close but I have almost nil free time for this stuff. Note that I have made it work and seen it in action. There'd be a patch two months ago if I hadn't decided to rebel against the way DMD did things*.Probably offering payment wouldn't be much of an enticement, but lobbying reasonable ideas here is a good way to go.Interesting....- Having property rewrites allows the special case for "array.length += foo;" to be removed. Property rewriting is the more general solution that will work for all properties and in arbitrary expressions.Agreed. By the way, I'm a huge fan of lowering; I think they are great for defining semantics in a principled way without a large language core. In recent times Walter has increasingly relied on lowerings and mentioned to me that the code savings in the compiler have been considerable.I wouldn't want to have to define functions for side-effectful operators /in addition/ to the getter and setter. The opIndexUnary/ opIndexOpAssign things have bugged me a bit because I've felt that the value returned from opIndex should handle its own operator overloads. I wonder if we are talking about two different things. The extra opIndexUnary/opIndexOpAssign overloads could supersede the behavior of getting from opIndex, mutating a temporary, and calling opIndexAssign with the temporary. I'd still like to not /need/ to define the extra operator overloads though. Indexing seems to be the general case of properties: an indexed expression can be a getter/setter pair identified by both an identifier (the property's name: opIndex in this case) and some runtime variables (the indices). The properties are a getter/setter pair identified by only the property's name alone. This isn't much harder to deal with: foo[i]++; -> {auto t = foo.opIndex(i); t++; foo.opIndex(i,t) }() Now if the index itself has side effects, then that expression must be removed: foo[i++]++; -> {auto t = foo.opIndex(i); t++; foo.opIndexAssign(i,t) i++; }() // i++ is removed from the indexing expression. I think I've managed to successfully deal with that. I've also given thought to the notion of side-effects within side-effects, and I make sure those are safely removed so that things don't get executed twice or more in an unexpected manner. And... I also handled out and ref parameters in function calls. A property found used as a ref argument is extracted from the call and replaced with a temporary that is get and set. I feel that out parameters are similar to assignment, so a property found as an out argument will only have its setter called. I just need to get the blasted thing to mesh with dmd's manner of travelling the AST ;)- By treating opIndex and opIndexAssign as properties then that pair alone will make cases like "a[i]++;" work correctly without the need for opIndexUnary overloads. Also "a[i] += foo" will work too, as well as anything else you haven't thought of yet.Well operator overloading handles indexing differently, and arguably better than in your proposal. Ideally we'd define operators on properties in a manner similar to the way indexing works in the new operator overloading scheme. I'll talk to Walter about that. Andrei
Mar 10 2010
On 03/10/2010 09:14 PM, Chad J wrote:Andrei Alexandrescu wrote:I hear you.Well operator overloading handles indexing differently, and arguably better than in your proposal. Ideally we'd define operators on properties in a manner similar to the way indexing works in the new operator overloading scheme. I'll talk to Walter about that. AndreiI wouldn't want to have to define functions for side-effectful operators /in addition/ to the getter and setter. The opIndexUnary/ opIndexOpAssign things have bugged me a bit because I've felt that the value returned from opIndex should handle its own operator overloads. I wonder if we are talking about two different things.The extra opIndexUnary/opIndexOpAssign overloads could supersede the behavior of getting from opIndex, mutating a temporary, and calling opIndexAssign with the temporary. I'd still like to not /need/ to define the extra operator overloads though.Yah, ideally both options should be available.Indexing seems to be the general case of properties: an indexed expression can be a getter/setter pair identified by both an identifier (the property's name: opIndex in this case) and some runtime variables (the indices). The properties are a getter/setter pair identified by only the property's name alone. This isn't much harder to deal with: foo[i]++; -> {auto t = foo.opIndex(i); t++; foo.opIndex(i,t) }()I considered and rejected that design because it has a number of important practical drawbacks, such as unsuitability for certain containers (hashes, sparse vectors) and inefficiency. Andrei
Mar 11 2010
Andrei Alexandrescu wrote:On 03/10/2010 09:14 PM, Chad J wrote:Oh. What would those drawbacks be? Note that I made a typo and wrote opIndex instead of opIndexAssign. I really meant... Indexing seems to be the general case of properties: an indexed expression can be a getter/setter pair identified by both an identifier (the property's name: opIndex in this case) and some runtime variables (the indices). The properties are a getter/setter pair identified by only the property's name alone. This isn't much harder to deal with: foo[i]++; -> {auto t = foo.opIndex(i); t++; foo.opIndex(i,t) }()I considered and rejected that design because it has a number of important practical drawbacks, such as unsuitability for certain containers (hashes, sparse vectors) and inefficiency. AndreiI'm assuming that the "design" you speak of is the getting/setting through indexing ops and not the overloading of opIndex to be a setter as well as a getter. Correct me if I'm wrong. - Chad{auto t = foo.opIndex(i); t++; foo.opIndexAssign(i,t) }()
Mar 11 2010
Andrei Alexandrescu:integration of interpretation with compilation,Isn't it better to use the compiler to run the functions at compile time, in a staged compilation? This removes the development & maintenance burden of the interpreter, that must be kept in sync with the semantics of the main compiler. A possible downside is that the compiler needs to be called many times, and this can slow down the main compilation. Bye, bearophile
Mar 10 2010
On 03/10/2010 01:05 PM, bearophile wrote:Andrei Alexandrescu:Staged compilation is an active research topic and many approaches could be better than what we have now. I was merely enumerating D features that are not present in mainstream languages. Andreiintegration of interpretation with compilation,Isn't it better to use the compiler to run the functions at compile time, in a staged compilation? This removes the development& maintenance burden of the interpreter, that must be kept in sync with the semantics of the main compiler. A possible downside is that the compiler needs to be called many times, and this can slow down the main compilation.
Mar 10 2010
On Tue, 09 Mar 2010 22:48:08 -0500, Chad J <chadjoan __spam.is.bad__gmail.com> wrote:I speak of the property rewriting where an expression like foo.prop++; is rewritten as auto t = foo.prop(); t++; foo.prop(t);I think this is fine as long as we don't take it to the extreme. That is, I don't want to see this happening: foo.prop1.prop2++; is rewritten to auto p1 = foo.prop1; auto p2 = p1.prop2; p2++; p1.prop2 = p2; foo.prop1 = p1; I think one level of lowering is enough to handle the most common cases. Of course, if a property returns an lvalue, then it should just work. -Steve
Mar 10 2010
On 03/10/2010 10:14 PM, Steven Schveighoffer wrote:I think this is fine as long as we don't take it to the extreme. That is, I don't want to see this happening: foo.prop1.prop2++; is rewritten to auto p1 = foo.prop1; auto p2 = p1.prop2; p2++; p1.prop2 = p2; foo.prop1 = p1; I think one level of lowering is enough to handle the most common cases. Of course, if a property returns an lvalue, then it should just work. -SteveWhy would you not want that? That's exactly what should happen! Why not? I'm sorry if I'm missing something obvious.
Mar 10 2010
On Wed, 10 Mar 2010 17:16:11 -0500, Pelle Månsson <pelle.mansson gmail.com> wrote:On 03/10/2010 10:14 PM, Steven Schveighoffer wrote:Hm... on second thought you are right. I meant to say something like this: foo.prop1.prop2.bar(); should not be rewritten in a similar fashion. ++ or op= in most cases should change the value of the property, but arbitrary functions are not as obvious. The other thing I don't like about this is it is difficult for the compiler to determine what is considered an rvalue or lvalue. Consider something like this: struct S { int x; int *y; ref S opAssignOpBinary(string op)(int other) { mixin("*y " ~ op ~ " other"); return this; } } I believe the compiler considers S an rvalue, but the operator for += will work as if it was an lvalue. To do that whole property shell-game for this will be a complete waste. It makes things like smart pointers perform way worse than they should. What may be a good-enough rule is that the property rewriting is done only if the end property (the one being affected) is a pure value type, or a builtin and the compiler can tell that the operation only affects that property. Without full code inspection, the "right" solution can't be had. -SteveI think this is fine as long as we don't take it to the extreme. That is, I don't want to see this happening: foo.prop1.prop2++; is rewritten to auto p1 = foo.prop1; auto p2 = p1.prop2; p2++; p1.prop2 = p2; foo.prop1 = p1; I think one level of lowering is enough to handle the most common cases. Of course, if a property returns an lvalue, then it should just work. -SteveWhy would you not want that? That's exactly what should happen! Why not? I'm sorry if I'm missing something obvious.
Mar 11 2010
On Wed, 10 Mar 2010 17:16:11 -0500, Pelle Månsson <pelle.mansson gmail.com> wrote:On 03/10/2010 10:14 PM, Steven Schveighoffer wrote:BTW, C# doesn't do this: struct C { private int _x; public int x { get { return _x; } set { _x = value; } } } struct D { private C _c; public C c { get { return _c; } set { _c = value; } } } class X { static void Main() { D d = new D(); d.c.x += 5; } } testme.cs(38,11): error CS1612: Cannot modify a value type return value of `D.c'. Consider storing the value in a temporary variable testme.cs(1,8): (Location of the symbol related to previous error) Compilation failed: 1 error(s), 0 warnings -SteveI think this is fine as long as we don't take it to the extreme. That is, I don't want to see this happening: foo.prop1.prop2++; is rewritten to auto p1 = foo.prop1; auto p2 = p1.prop2; p2++; p1.prop2 = p2; foo.prop1 = p1; I think one level of lowering is enough to handle the most common cases. Of course, if a property returns an lvalue, then it should just work. -SteveWhy would you not want that? That's exactly what should happen! Why not? I'm sorry if I'm missing something obvious.
Mar 11 2010
Thu, 11 Mar 2010 15:37:59 -0500, Steven Schveighoffer wrote:On Wed, 10 Mar 2010 17:16:11 -0500, Pelle Månsson <pelle.mansson gmail.com> wrote:I hope that cannot be used as an argument against the feature. Scala supports chained properties merrily just like it should. Sorry for posting, I'll try to avoid that in the future.On 03/10/2010 10:14 PM, Steven Schveighoffer wrote:BTW, C# doesn't do this: struct C { private int _x; public int x { get { return _x; } set { _x = value; } } } struct D { private C _c; public C c { get { return _c; } set { _c = value; } } } class X { static void Main() { D d = new D(); d.c.x += 5; } }I think this is fine as long as we don't take it to the extreme. That is, I don't want to see this happening: foo.prop1.prop2++; is rewritten to auto p1 = foo.prop1; auto p2 = p1.prop2; p2++; p1.prop2 = p2; foo.prop1 = p1; I think one level of lowering is enough to handle the most common cases. Of course, if a property returns an lvalue, then it should just work. -SteveWhy would you not want that? That's exactly what should happen! Why not? I'm sorry if I'm missing something obvious.
Mar 11 2010
On 03/11/2010 09:37 PM, Steven Schveighoffer wrote:BTW, C# doesn't do this: -SteveI still think D should, it makes little sense not to. What is gained from limiting arbitrarily?
Mar 12 2010
On Fri, 12 Mar 2010 04:06:27 -0500, Pelle Månsson <pelle.mansson gmail.com> wrote:On 03/11/2010 09:37 PM, Steven Schveighoffer wrote:It has been pointed out that C#'s properties are "right" after 4 years of development. I was just pointing out that C# doesn't agree with what has been proposed. I am undecided whether I like the idea of chained properties performing this trick. As long as we can guarantee that it truly is the correct choice on the compiler's part, I have no problem. This may mean disallowing compilation a la C# in certain cases where the compiler is unsure. You can always workaround by writing the steps manually (as the C# error message suggests). -SteveBTW, C# doesn't do this: -SteveI still think D should, it makes little sense not to. What is gained from limiting arbitrarily?
Mar 12 2010