digitalmars.D - DIP28, on properties, availabel for destruction as well
- deadalnix (5/5) Feb 27 2013 Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28
- Lars T. Kyllingstad (4/9) Feb 27 2013 I like both this one and DIP27. But I do think it is way too late
- Jonathan M Davis (5/11) Feb 27 2013 And what does this provide over DIP23 aside from the fact that now it's
- deadalnix (17/30) Feb 27 2013 It doesn't have special cases.
- Chris Cain (13/17) Feb 27 2013 +1. Properties (from what I've seen) are suppose to be
- Jacob Carlborg (31/34) Feb 27 2013 What happens if you do:
- deadalnix (6/41) Feb 27 2013 The proposal is to rewrite that to auto a = b.setter(3);
- Jacob Carlborg (10/14) Feb 28 2013 Then setters always must return a value. I think it would be better to
- deadalnix (11/20) Feb 28 2013 Must is not appropriate here, as it isn't an obligation at all. I
- Jacob Carlborg (6/12) Feb 28 2013 My concern here is setters that doesn't return a value. They won't work
- deadalnix (5/20) Feb 28 2013 That is up to the writer of the setter. Note that you can also
- Jacob Carlborg (4/7) Feb 28 2013 I think that's not a property by definition.
- angel (10/10) Feb 28 2013 Possibly setters had better have 'void' as their return type.
- Artur Skawina (12/20) Feb 28 2013
- Timon Gehr (4/7) Mar 02 2013 Ignoring complexities and complications is not called simplicity, it's
- deadalnix (3/13) Mar 02 2013 It be simplism if reduced the expressiveness of the language. It
- deadalnix (13/23) Mar 02 2013 DIP24 and DIP28 are very similar in regard of property, that is
- Timon Gehr (8/31) Mar 02 2013 Consistent support for multiple assignment.
- deadalnix (7/24) Mar 13 2013 It isn't prevented by DIP28. Plus, this is already the behavior
- Timon Gehr (15/43) Mar 13 2013 Well, I do not feel particularly strongly about it. It is moved to
- deadalnix (4/20) Mar 13 2013 I do not feel strongly about it, however, the consistency with
- Artur Skawina (7/8) Mar 14 2013 Compiler optimization territory. The compiler can clone the function, cr...
- deadalnix (3/21) Mar 14 2013 It can't when it come to copy contructor/destructor of structs if
- Artur Skawina (14/25) Mar 14 2013 That's what I meant by "can get a bit more interesting, specially for no...
- Timon Gehr (8/33) Mar 14 2013 Which useful constructs?
- Artur Skawina (21/60) Mar 14 2013 It was a generic comment. I don't think discussing details about these D...
- Timon Gehr (10/16) Mar 13 2013 (x?setter1:setter2)=y; // ?
- deadalnix (16/35) Mar 13 2013 With DIP28, it do not work. I do agree this is problem for ,
Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.
Feb 27 2013
On Wednesday, 27 February 2013 at 15:46:38 UTC, deadalnix wrote:Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.I like both this one and DIP27. But I do think it is way too late for D2. Lars
Feb 27 2013
On Wednesday, February 27, 2013 16:46:37 deadalnix wrote:Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.And what does this provide over DIP23 aside from the fact that now it's impossible to get the address of a property function (which of course is a problem)? - Jonathan M Davis
Feb 27 2013
On Wednesday, 27 February 2013 at 17:56:10 UTC, Jonathan M Davis wrote:On Wednesday, February 27, 2013 16:46:37 deadalnix wrote:It doesn't have special cases. As of taking the address of a property, we should simply allow the compiler to optimize away lambda when they are of the form : a => fun(a); when it make sens to do so. This is easy to recognize for the compiler. Additionally, I don't think this is really a problem as it is asking to break the abstraction, plain and simple. If you need a function pointer, then it is likely that you shouldn't be using a property in the first place. Every signle field access involve some operation, sometime even a complex one (TLS on OSX for instance). And you can't get a function pointer on that, and this haven't been a problem for anyone so far. The compiler propose some routines to interact with data, and properties allow the user to propose its own.Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.And what does this provide over DIP23 aside from the fact that now it's impossible to get the address of a property function (which of course is a problem)?
Feb 27 2013
On Thursday, 28 February 2013 at 02:56:40 UTC, deadalnix wrote:Additionally, I don't think this is really a problem as it is asking to break the abstraction, plain and simple. If you need a function pointer, then it is likely that you shouldn't be using a property in the first place.+1. Properties (from what I've seen) are suppose to be effectively indistinguishable between a field. If you're taking the address of a property hoping to get the function address, this is a clear violation of that. For instance, if I wrote some code like this: ... auto myFun = &b.front; ... And I expected to get a function pointer from that, it would be a clear violation of what ".front" means (or, is intended to mean...) and it would break on many ranges because many of them are implemented s.t. front is actually a field.
Feb 27 2013
On 2013-02-27 16:46, deadalnix wrote:Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.What happens if you do: auto a = b.setter = 3; I see two alternatives: A. It's rewritten to this: auto __tmp = 3; b.setter = 3; auto a = __tmp; B. It's rewritten to this: b.setter = 3; auto a = b.getter; I prefer B. What happens if you do: struct Point { int x; int y; } class Widget { property Point getter(); property Point setter(Point); } auto w = new Widget; w.getter.x = 3; I would prefer if that gets rewritten to: Point __tmp = w.getter; __tmp.x = 3; w.getter = __tmp; -- /Jacob Carlborg
Feb 27 2013
On Wednesday, 27 February 2013 at 20:09:51 UTC, Jacob Carlborg wrote:On 2013-02-27 16:46, deadalnix wrote:The proposal is to rewrite that to auto a = b.setter(3); Its value is whatever the setter returns.Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.What happens if you do: auto a = b.setter = 3; I see two alternatives: A. It's rewritten to this: auto __tmp = 3; b.setter = 3; auto a = __tmp; B. It's rewritten to this: b.setter = 3; auto a = b.getter; I prefer B.What happens if you do: struct Point { int x; int y; } class Widget { property Point getter(); property Point setter(Point); } auto w = new Widget; w.getter.x = 3;Error, w.getter is not an lvalue.I would prefer if that gets rewritten to: Point __tmp = w.getter; __tmp.x = 3; w.getter = __tmp;That would be an error as well, for the same reason.
Feb 27 2013
On 2013-02-28 04:00, deadalnix wrote:The proposal is to rewrite that to auto a = b.setter(3); Its value is whatever the setter returns.Then setters always must return a value. I think it would be better to have the compiler rewrite the expression to return what the getter returns.Error, w.getter is not an lvalue.Then you cannot freely change a field to a property.That would be an error as well, for the same reason.That should have of course looked like: w.setter = __tmp; If this rewrite is not done then again, you cannot freely change a field to a property. -- /Jacob Carlborg
Feb 28 2013
On Thursday, 28 February 2013 at 08:02:05 UTC, Jacob Carlborg wrote:On 2013-02-28 04:00, deadalnix wrote:Must is not appropriate here, as it isn't an obligation at all. I don't really see what is the concern here. If the function is simple, then it will be inlined and unused returned values can be optimized away. If the function is complex, the cost of returning something when not needed will be negligible anyway. What is your concern here ?The proposal is to rewrite that to auto a = b.setter(3); Its value is whatever the setter returns.Then setters always must return a value. I think it would be better to have the compiler rewrite the expression to return what the getter returns.You can return an lvalue. But you example was returning an rvalue; so it is an error in this case.Error, w.getter is not an lvalue.Then you cannot freely change a field to a property.
Feb 28 2013
On 2013-02-28 09:21, deadalnix wrote:Must is not appropriate here, as it isn't an obligation at all. I don't really see what is the concern here. If the function is simple, then it will be inlined and unused returned values can be optimized away. If the function is complex, the cost of returning something when not needed will be negligible anyway. What is your concern here ?My concern here is setters that doesn't return a value. They won't work with chained assignments. Another thing that will break when changing a filed to a property. -- /Jacob Carlborg
Feb 28 2013
On Thursday, 28 February 2013 at 13:06:39 UTC, Jacob Carlborg wrote:On 2013-02-28 09:21, deadalnix wrote:That is up to the writer of the setter. Note that you can also create getter that returns void. It is even more stupid. As long as it isn't error prone.Must is not appropriate here, as it isn't an obligation at all. I don't really see what is the concern here. If the function is simple, then it will be inlined and unused returned values can be optimized away. If the function is complex, the cost of returning something when not needed will be negligible anyway. What is your concern here ?My concern here is setters that doesn't return a value. They won't work with chained assignments. Another thing that will break when changing a filed to a property.
Feb 28 2013
On 2013-02-28 15:45, deadalnix wrote:That is up to the writer of the setter. Note that you can also create getter that returns void. It is even more stupid. As long as it isn't error prone.I think that's not a property by definition. -- /Jacob Carlborg
Feb 28 2013
Possibly setters had better have 'void' as their return type. Then auto a = b.setter = 3; will have the predictable behavior with both 'a' and 'whatever b-setter sets' being set to 3. Otherwise, it might be totally unpredictable. On the other hand, possibly setters MUST return a value of the same type they accept, in order to be able to emulate standard-like behavior. When I re-read it, the 1-st option looks cleaner.
Feb 28 2013
On 02/28/13 14:33, angel wrote:Possibly setters had better have 'void' as their return type. Then auto a = b.setter = 3; will have the predictable behavior with both 'a' and 'whatever b-setter sets' being set to 3. Otherwise, it might be totally unpredictable. On the other hand, possibly setters MUST return a value of the same type they accept, in order to be able to emulate standard-like behavior. When I re-read it, the 1-st option looks cleaner.... long setter(long v) property; ... auto a = b.setter = 3; // and there's no reason to disallow: long setter(ubyte v) property; long setter(T:long)(T v) property; long setter(U)(U v) property; // etc artur
Feb 28 2013
There _is_ reason. You may, possibly, argue this reason is not important enough - here you might be right or wrong, I don't know. The point is a property should behave as close as possible to a real variable: class A { int field; } auto a = new A(); auto x = a.field = 3; Now you 'upgrade' 'field' to a property class A { int _field; property ??? field(int val) { _field = val; } } auto a = new A(); auto x = a.field = 3; The above line should behave _identically_ to the previous case. Will it, if you define " property char field(int val)" ? Apparently no.
Feb 28 2013
On Thursday, 28 February 2013 at 14:55:06 UTC, angel wrote:There _is_ reason. You may, possibly, argue this reason is not important enough - here you might be right or wrong, I don't know. The point is a property should behave as close as possible to a real variable: class A { int field; } auto a = new A(); auto x = a.field = 3; Now you 'upgrade' 'field' to a property class A { int _field; property ??? field(int val) { _field = val;return _field = val;} } auto a = new A(); auto x = a.field = 3; The above line should behave _identically_ to the previous case. Will it, if you define " property char field(int val)" ? Apparently no.The current proposal is simpler and allow more. It surely does allow to do crazy stupid things, but you can't really allow more without allowing to do dumb things.
Feb 28 2013
On 02/27/2013 04:46 PM, deadalnix wrote:Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.Ignoring complexities and complications is not called simplicity, it's simplism. DIP27 s a simplistic subset of DIP24.
Mar 02 2013
On Saturday, 2 March 2013 at 16:00:55 UTC, Timon Gehr wrote:On 02/27/2013 04:46 PM, deadalnix wrote:It be simplism if reduced the expressiveness of the language. It doesn't.Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.Ignoring complexities and complications is not called simplicity, it's simplism. DIP27 s a simplistic subset of DIP24.
Mar 02 2013
On Saturday, 2 March 2013 at 16:00:55 UTC, Timon Gehr wrote:On 02/27/2013 04:46 PM, deadalnix wrote:DIP24 and DIP28 are very similar in regard of property, that is exact. (As it is in DIP28 topic, I assume that you meant DIP28). Main difference I see : - Introduction of __traits(propertyAccessors, propertySymbol) . This is loosely correlated to the content of each DIP. Both can do with or without. - typeof(__traits(propertyAccessors, prop)(exp)) is void and its result is used. I don't see the point of special casing this. It increase complexity and reduces what you can express. It is unclear what happen when the property is aliased or passed as alias parameter in both DIP, and should be effectively corrected.Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.Ignoring complexities and complications is not called simplicity, it's simplism. DIP27 s a simplistic subset of DIP24.
Mar 02 2013
On 03/02/2013 05:22 PM, deadalnix wrote:On Saturday, 2 March 2013 at 16:00:55 UTC, Timon Gehr wrote:Agreed.On 02/27/2013 04:46 PM, deadalnix wrote:DIP24 and DIP28 are very similar in regard of property, that is exact. (As it is in DIP28 topic, I assume that you meant DIP28). Main difference I see : - Introduction of __traits(propertyAccessors, propertySymbol) . This is loosely correlated to the content of each DIP. Both can do with or without.Here come the sister of DIP27 : DIP28 http://wiki.dlang.org/DIP28 . It address specifically properties. A 3rd one is coming on delegate. As for DIP27, the goal is to go aggressively for simplicity.Ignoring complexities and complications is not called simplicity, it's simplism. DIP27 s a simplistic subset of DIP24.- typeof(__traits(propertyAccessors, prop)(exp)) is void and its result is used. I don't see the point of special casing this.Consistent support for multiple assignment.It increase complexityYup, marginally.and reduces what you can express.Not strictly.It is unclear what happen when the property is aliased or passed as alias parameter in both DIP, and should be effectively corrected.No, both DIPs specify it exactly. DIP28 is broken in that regard. But DIP28 leaves it up to imagination what it means for an expression to occur in the left-hand side of an assignment.
Mar 02 2013
On Saturday, 2 March 2013 at 16:48:14 UTC, Timon Gehr wrote:It isn't prevented by DIP28. Plus, this is already the behavior of opAssign and firends.- typeof(__traits(propertyAccessors, prop)(exp)) is void and its result is used. I don't see the point of special casing this.Consistent support for multiple assignment.It does. I''m not sure that the extra possibility are really useful, but I'm reluctant to increase complexity to reduce expression capabilities (unless they cause real problems).It increase complexityYup, marginally.and reduces what you can express.Not strictly.DIP28 is fixed in that regard. You were right.It is unclear what happen when the property is aliased or passed as alias parameter in both DIP, and should be effectively corrected.No, both DIPs specify it exactly. DIP28 is broken in that regard. But DIP28 leaves it up to imagination what it means for an expression to occur in the left-hand side of an assignment.
Mar 13 2013
On 03/13/2013 04:55 PM, deadalnix wrote:On Saturday, 2 March 2013 at 16:48:14 UTC, Timon Gehr wrote:Well, I do not feel particularly strongly about it. It is moved to possible extensions now. It should then probably also apply to opAssign and friends.It isn't prevented by DIP28. Plus, this is already the behavior of opAssign and firends.- typeof(__traits(propertyAccessors, prop)(exp)) is void and its result is used. I don't see the point of special casing this.Consistent support for multiple assignment.In some ways, and in other ways expressiveness is extended, therefore it does not _strictly_ reduce expressiveness. I do not think that the kind of expressiveness removed is useful. Why would it be?It does.It increase complexityYup, marginally.and reduces what you can express.Not strictly.I''m not sure that the extra possibility are really useful, but I'm reluctant to increase complexity to reduce expression capabilities (unless they cause real problems).Currently there might be unnecessary overhead for returning a result if it is not used. Since a property will usually hold on to the value, this can be a problem if a struct is expensive to copy. Hence the implementer may choose to not support multiple assignment for performance reasons (justified or, usually, unjustified). Hence generic code cannot rely on multiple assignment working, which is not nice.Ok, will check.DIP28 is fixed in that regard. You were right.It is unclear what happen when the property is aliased or passed as alias parameter in both DIP, and should be effectively corrected.No, both DIPs specify it exactly. DIP28 is broken in that regard. But DIP28 leaves it up to imagination what it means for an expression to occur in the left-hand side of an assignment.
Mar 13 2013
On Wednesday, 13 March 2013 at 20:16:17 UTC, Timon Gehr wrote:On 03/13/2013 04:55 PM, deadalnix wrote:I do not feel strongly about it, however, the consistency with opAssign and friend seems to me like the most important thing. We got to change both to use the void trick, or none.On Saturday, 2 March 2013 at 16:48:14 UTC, Timon Gehr wrote:Well, I do not feel particularly strongly about it. It is moved to possible extensions now. It should then probably also apply to opAssign and friends.It isn't prevented by DIP28. Plus, this is already the behavior of opAssign and firends.- typeof(__traits(propertyAccessors, prop)(exp)) is void and its result is used. I don't see the point of special casing this.Consistent support for multiple assignment.
Mar 13 2013
On 03/13/13 21:16, Timon Gehr wrote:Currently there might be unnecessary overhead for returning a result if it is not used. Since a property will usually hold on to the value, this can be a problem if a struct is expensive to copy. Hence the implementer may choose to not support multiple assignment for performance reasons (justified or, usually, unjustified). Hence generic code cannot rely on multiple assignment working, which is not nice.Compiler optimization territory. The compiler can clone the function, create a copy that doesn't return a result; callers that don't need one (and don't inline the callee) can then use that clone. The case where a function always returns the argument (like property setters will typically do) can also be handled more efficiently (yes; this can get a bit more interesting, specially for non-pod types). artur
Mar 14 2013
On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:On 03/13/13 21:16, Timon Gehr wrote:It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.Currently there might be unnecessary overhead for returning a result if it is not used. Since a property will usually hold on to the value, this can be a problem if a struct is expensive to copy. Hence the implementer may choose to not support multiple assignment for performance reasons (justified or, usually, unjustified). Hence generic code cannot rely on multiple assignment working, which is not nice.Compiler optimization territory. The compiler can clone the function, create a copy that doesn't return a result; callers that don't need one (and don't inline the callee) can then use that clone. The case where a function always returns the argument (like property setters will typically do) can also be handled more efficiently (yes; this can get a bit more interesting, specially for non-pod types). artur
Mar 14 2013
On 03/14/13 12:42, deadalnix wrote:On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:That's what I meant by "can get a bit more interesting, specially for non-pod types". But it can be done, the "interesting" parts may involve other language changes. W/o changes, /some/ (non-pod) cases can still be handled; it's just that I'm going for a complete solution, not just allowing a small subset and "fixing" the rest of the problem by banning useful constructs. My point is that designing the language around compiler limitations (which aren't always even there) is wrong. Especially in situations like this one, where the problematic case is rare, and will get less problematic eventually when the language evolves. We're talking only about callers that actually use the results of setters - optimizing for this case is fine, but defining the language specifically to avoid the rare case, which will take a small perf hit (well, actually not improve, that cost already exists), does not seem justified. arturOn 03/13/13 21:16, Timon Gehr wrote:It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.Currently there might be unnecessary overhead for returning a result if it is not used. Since a property will usually hold on to the value, this can be a problem if a struct is expensive to copy. Hence the implementer may choose to not support multiple assignment for performance reasons (justified or, usually, unjustified). Hence generic code cannot rely on multiple assignment working, which is not nice.Compiler optimization territory. The compiler can clone the function, create a copy that doesn't return a result; callers that don't need one (and don't inline the callee) can then use that clone. The case where a function always returns the argument (like property setters will typically do) can also be handled more efficiently (yes; this can get a bit more interesting, specially for non-pod types).
Mar 14 2013
On 03/14/2013 01:26 PM, Artur Skawina wrote:On 03/14/13 12:42, deadalnix wrote:What's an important case not considered?On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:That's what I meant by "can get a bit more interesting, specially for non-pod types". But it can be done, the "interesting" parts may involve other language changes. W/o changes, /some/ (non-pod) cases can still be handled; it's just that I'm going for a complete solution, not just allowing a small subsetOn 03/13/13 21:16, Timon Gehr wrote:It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.Currently there might be unnecessary overhead for returning a result if it is not used. Since a property will usually hold on to the value, this can be a problem if a struct is expensive to copy. Hence the implementer may choose to not support multiple assignment for performance reasons (justified or, usually, unjustified). Hence generic code cannot rely on multiple assignment working, which is not nice.Compiler optimization territory. The compiler can clone the function, create a copy that doesn't return a result; callers that don't need one (and don't inline the callee) can then use that clone. The case where a function always returns the argument (like property setters will typically do) can also be handled more efficiently (yes; this can get a bit more interesting, specially for non-pod types).and "fixing" the rest of the problem by banning useful constructs.Which useful constructs?My point is that designing the language around compiler limitations (which aren't always even there) is wrong.Why do you use D then? If only language expressiveness matters, D is not at the top.Especially in situations like this one, where the problematic case is rare, and will get less problematic eventually when the language evolves. We're talking only about callers that actually use the results of setters - optimizing for this case is fine, but defining the language specifically to avoid the rare case, which will take a small perf hit (well, actually not improve, that cost already exists), does not seem justified.Didn't get any of this. It's not too common that the perf hit _exists_, but if it does, the common case at the call site is that it is taken.
Mar 14 2013
On 03/14/13 18:20, Timon Gehr wrote:On 03/14/2013 01:26 PM, Artur Skawina wrote:It was a generic comment. I don't think discussing details about these DIPs makes sense, as, as somebody else already pointed out, they don't mean much, w/o actual implementations. The proposals may have problems, but as they aren't likely to impact D in any way whatsoever, I consider the existence of these DIPs to be mostly harmless. There are far more serious dangers to D. Hmm. Anyway, are you proposing that property setters could optionally return 'void' and would then evaluate to the first (only) arg? That might actually work; but I haven't seen it mentioned anywhere. If that was what you were referring to, then I must have missed it.On 03/14/13 12:42, deadalnix wrote:What's an important case not considered?On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:That's what I meant by "can get a bit more interesting, specially for non-pod types". But it can be done, the "interesting" parts may involve other language changes. W/o changes, /some/ (non-pod) cases can still be handled; it's just that I'm going for a complete solution, not just allowing a small subsetOn 03/13/13 21:16, Timon Gehr wrote:It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.Currently there might be unnecessary overhead for returning a result if it is not used. Since a property will usually hold on to the value, this can be a problem if a struct is expensive to copy. Hence the implementer may choose to not support multiple assignment for performance reasons (justified or, usually, unjustified). Hence generic code cannot rely on multiple assignment working, which is not nice.Compiler optimization territory. The compiler can clone the function, create a copy that doesn't return a result; callers that don't need one (and don't inline the callee) can then use that clone. The case where a function always returns the argument (like property setters will typically do) can also be handled more efficiently (yes; this can get a bit more interesting, specially for non-pod types).and "fixing" the rest of the problem by banning useful constructs.Which useful constructs?I wish i could really /use/ D. But it's hard to use it when you encounter serious problems every ~2 pages of non-trivial code. Either a) compiler limitations, b) compiler bugs, or c) language problems. The language improves, even if very slowly, and it would be better if it didn't regress before it gets better, which unfortunately seems to be a possibility recently... D is the best thing that could have happened to C, and we can only hope that Walter is able to resist.My point is that designing the language around compiler limitations (which aren't always even there) is wrong.Why do you use D then? If only language expressiveness matters, D is not at the top.And /that/ common case could be avoided. But I'm not even sure that it /is/ the common case, as i suspect most property accessors are being inlined. So it's mostly about the non-inline-non-pod-returning extremely complex property implementations. Which I don't think is a case worth optimizing the language for. arturEspecially in situations like this one, where the problematic case is rare, and will get less problematic eventually when the language evolves. We're talking only about callers that actually use the results of setters - optimizing for this case is fine, but defining the language specifically to avoid the rare case, which will take a small perf hit (well, actually not improve, that cost already exists), does not seem justified.Didn't get any of this. It's not too common that the perf hit _exists_, but if it does, the common case at the call site is that it is taken.
Mar 14 2013
On 03/13/2013 04:55 PM, deadalnix wrote:...(x?setter1:setter2)=y; // ? (x, setter)=y; // ? struct S{ ref int foo(){ ... } int foo(int x){ ... } } S x; x.foo+=2; // ? getter.x=y; // ? (x is a field of typeof(getter))No, both DIPs specify it exactly. DIP28 is broken in that regard. But DIP28 leaves it up to imagination what it means for an expression to occur in the left-hand side of an assignment.DIP28 is fixed in that regard. You were right.
Mar 13 2013
On Wednesday, 13 March 2013 at 20:21:27 UTC, Timon Gehr wrote:On 03/13/2013 04:55 PM, deadalnix wrote:With DIP28, it do not work. I do agree this is problem for , operator, not sure for ?: . http://dlang.org/expression.html#ConditionalExpression say nothing about rvaluesness or lvalueness of both , and ?: expressions in general. It should probably be defined in the general case and this should drive property definition. I feel like DIP28 is broken with comma expression and that DIP24 is right on that. I honestly don't really know about ?: expressions....(x?setter1:setter2)=y; // ? (x, setter)=y; // ?No, both DIPs specify it exactly. DIP28 is broken in that regard. But DIP28 leaves it up to imagination what it means for an expression to occur in the left-hand side of an assignment.DIP28 is fixed in that regard. You were right.struct S{ ref int foo(){ ... } int foo(int x){ ... } } S x; x.foo+=2; // ?This is clearly ambiguous. I feel like the getter solution should take precedence if that make sense or simply disallow setter when getter return an lvalue (as it create all kind of situation when you don't know what is called).getter.x=y; // ? (x is a field of typeof(getter))If getter return an rvalue, then it fail. If getter return an lvalue, it does work.
Mar 13 2013