www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP28, on properties, availabel for destruction as well

reply "deadalnix" <deadalnix gmail.com> writes:
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
next sibling parent "Lars T. Kyllingstad" <public kyllingen.net> writes:
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
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
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
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
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
next sibling parent reply Jacob Carlborg <doob me.com> writes:
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
parent reply Jacob Carlborg <doob me.com> writes:
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
parent Jacob Carlborg <doob me.com> writes:
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
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
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
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 27 February 2013 at 17:56:10 UTC, Jonathan M Davis 
wrote:
 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)?

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.
Feb 27 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 27 February 2013 at 20:09:51 UTC, Jacob Carlborg 
wrote:
 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.

The proposal is to rewrite that to auto a = b.setter(3); Its value is whatever the setter returns.
 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
prev sibling next sibling parent "Chris Cain" <clcain uncg.edu> writes:
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
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 28 February 2013 at 08:02:05 UTC, Jacob Carlborg 
wrote:
 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.

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 ?
 Error, w.getter is not an lvalue.

Then you cannot freely change a field to a property.

You can return an lvalue. But you example was returning an rvalue; so it is an error in this case.
Feb 28 2013
prev sibling next sibling parent "angel" <andrey.gelman gmail.com> writes:
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
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 28 February 2013 at 13:06:39 UTC, Jacob Carlborg 
wrote:
 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.

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.
Feb 28 2013
prev sibling next sibling parent "angel" <andrey.gelman gmail.com> writes:
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
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
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
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 03/02/2013 05:22 PM, deadalnix wrote:
 On Saturday, 2 March 2013 at 16:00:55 UTC, Timon Gehr wrote:
 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.

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.

Agreed.
   - 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 complexity

Yup, 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
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 03/13/2013 04:55 PM, deadalnix wrote:
 On Saturday, 2 March 2013 at 16:48:14 UTC, Timon Gehr wrote:
  - 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 isn't prevented by DIP28. Plus, this is already the behavior of opAssign and firends.

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 increase complexity

Yup, marginally.
 and reduces what you can express.

Not strictly.

It does.

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?
 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.
 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.

DIP28 is fixed in that regard. You were right.

Ok, will check.
Mar 13 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/14/2013 01:26 PM, Artur Skawina wrote:
 On 03/14/13 12:42, deadalnix wrote:
 On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:
 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).

It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.

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

What's an important case not considered?
 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
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 03/14/13 18:20, Timon Gehr wrote:
 On 03/14/2013 01:26 PM, Artur Skawina wrote:
 On 03/14/13 12:42, deadalnix wrote:
 On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:
 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).

It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.

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

What's an important case not considered?
 and "fixing" the rest of the problem by banning useful constructs.

Which useful constructs?

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

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

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. artur
Mar 14 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/13/2013 04:55 PM, deadalnix wrote:
 ...
 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.

(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))
Mar 13 2013
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
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
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 03/14/13 12:42, deadalnix wrote:
 On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:
 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).

It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.

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. artur
Mar 14 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 2 March 2013 at 16:00:55 UTC, Timon Gehr wrote:
 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.

It be simplism if reduced the expressiveness of the language. It doesn't.
Mar 02 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 2 March 2013 at 16:00:55 UTC, Timon Gehr wrote:
 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.

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.
Mar 02 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 2 March 2013 at 16:48:14 UTC, Timon Gehr wrote:
  - 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 isn't prevented by DIP28. Plus, this is already the behavior of opAssign and firends.
 It increase complexity

Yup, marginally.
 and reduces what you can express.

Not strictly.

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

DIP28 is fixed in that regard. You were right.
Mar 13 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 13 March 2013 at 20:16:17 UTC, Timon Gehr wrote:
 On 03/13/2013 04:55 PM, deadalnix wrote:
 On Saturday, 2 March 2013 at 16:48:14 UTC, Timon Gehr wrote:
 - 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 isn't prevented by DIP28. Plus, this is already the behavior of opAssign and firends.

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.

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.
Mar 13 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 13 March 2013 at 20:21:27 UTC, Timon Gehr wrote:
 On 03/13/2013 04:55 PM, deadalnix wrote:
 ...
 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.

(x?setter1:setter2)=y; // ? (x, setter)=y; // ?

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.
 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
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 14 March 2013 at 11:04:44 UTC, Artur Skawina wrote:
 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

It can't when it come to copy contructor/destructor of structs if they aren't pure and trivials.
Mar 14 2013