March 13, 2013
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.
March 13, 2013
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.
March 13, 2013
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))

March 14, 2013
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.
March 14, 2013
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.
March 14, 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
March 14, 2013
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.
March 14, 2013
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
March 14, 2013
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.
March 14, 2013
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
1 2 3
Next ›   Last »