August 17, 2020 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On 8/17/20 4:53 PM, mw wrote:
> On Monday, 17 August 2020 at 18:10:16 UTC, H. S. Teoh wrote:
>> On Mon, Aug 17, 2020 at 05:58:16PM +0000, mw via Digitalmars-d wrote:
>>> On Monday, 17 August 2020 at 17:15:59 UTC, H. S. Teoh wrote:
>> [...]
>>> > Chain assignment fix: > https://github.com/dlang/phobos/pull/7599
>>>
>>> Thanks for the PR, I just added comments: does this fix also work for mixed native & checked chain assignment? i.e. add to unittest:
>>>
>>> ```
>>> long la, lb;
>>> Checked!long ca, cb;
>>>
>>> la = ca = lb = cb; // mixed chain assign
>>> ca = la = cb = lb;
>>> ```
>>
>> Currently, it doesn't work. I'm on the fence about whether it should: the whole point of using Checked is that you don't want to automatically convert to the native type because the converted value will lose the protections conferred by Check. Assigning a Checked to a native type *might* be a mistake - you thought the variable was Checked but it wasn't, so subsequent operations on it no longer has Checked semantics even though
>
> Yes, that's the principle we all agree. However, we are talking about opAssign() here.
>
> The user specifies his/her intention via the variable's type declaration, e.g. native `long` vs checked `Long`. The *subsequent* operations you talking about will be on user specified variable (type), there will be no surprise here: if the LHS is declared as a `long`, the subsequent operations will be on `long`, and if the LHS is `Long`, the subsequent operations will be on `Long`, all as user has specified.
>
> opAssign() just make the boxing/unboxing life easier between these two types. And there is not any mathematical operation performed inside opAssign(), hence for this particular function, native == checked is always true. So I think let opAssign() return the underlying type will make the drop-in replacement process more smooth, and without extra correctness concern.
Whenever I implement opAssign I have it return void and try to remember to propose that the compiler takes care of chained assignments by itself.
Requiring user-defined assignment to `return *this;` was goofy in C++. Requiring user-defined assignment to `return this;` is goofy in D. Assignment should return void and the compiler should take care of it.
|
August 18, 2020 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 18 August 2020 at 01:23:01 UTC, Andrei Alexandrescu wrote:
> On 8/17/20 4:53 PM, mw wrote:
>> On Monday, 17 August 2020 at 18:10:16 UTC, H. S. Teoh wrote:
>>> On Mon, Aug 17, 2020 at 05:58:16PM +0000, mw via Digitalmars-d wrote:
>>>> On Monday, 17 August 2020 at 17:15:59 UTC, H. S. Teoh wrote:
>>> [...]
>>>> > Chain assignment fix: > https://github.com/dlang/phobos/pull/7599
>>>>
>>>> Thanks for the PR, I just added comments: does this fix also work for mixed native & checked chain assignment? i.e. add to unittest:
>>>>
>>>> ```
>>>> long la, lb;
>>>> Checked!long ca, cb;
>>>>
>>>> la = ca = lb = cb; // mixed chain assign
>>>> ca = la = cb = lb;
>>>> ```
>>>
>>> Currently, it doesn't work. I'm on the fence about whether it should: the whole point of using Checked is that you don't want to automatically convert to the native type because the converted value will lose the protections conferred by Check. Assigning a Checked to a native type *might* be a mistake - you thought the variable was Checked but it wasn't, so subsequent operations on it no longer has Checked semantics even though
>>
>> Yes, that's the principle we all agree. However, we are talking about opAssign() here.
>>
>> The user specifies his/her intention via the variable's type declaration, e.g. native `long` vs checked `Long`. The *subsequent* operations you talking about will be on user specified variable (type), there will be no surprise here: if the LHS is declared as a `long`, the subsequent operations will be on `long`, and if the LHS is `Long`, the subsequent operations will be on `Long`, all as user has specified.
>>
>> opAssign() just make the boxing/unboxing life easier between these two types. And there is not any mathematical operation performed inside opAssign(), hence for this particular function, native == checked is always true. So I think let opAssign() return the underlying type will make the drop-in replacement process more smooth, and without extra correctness concern.
>
> Whenever I implement opAssign I have it return void and try to remember to propose that the compiler takes care of chained assignments by itself.
>
> Requiring user-defined assignment to `return *this;` was goofy in C++. Requiring user-defined assignment to `return this;` is goofy in D. Assignment should return void and the compiler should take care of it.
Right, the library fix (work-around) is sub-optimal, it's better be fixed by the compiler.
@Walter, it's your turn :-)
|
August 17, 2020 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Mon, Aug 17, 2020 at 09:23:01PM -0400, Andrei Alexandrescu via Digitalmars-d wrote: [...] > Whenever I implement opAssign I have it return void and try to remember to propose that the compiler takes care of chained assignments by itself. > > Requiring user-defined assignment to `return *this;` was goofy in C++. Requiring user-defined assignment to `return this;` is goofy in D. Assignment should return void and the compiler should take care of it. +1. Is there an enhancement request for this? As Walter often says, if it's not in bugzilla, it doesn't exist. ;-) T -- If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell |
August 18, 2020 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 8/18/20 1:07 AM, H. S. Teoh wrote: > On Mon, Aug 17, 2020 at 09:23:01PM -0400, Andrei Alexandrescu via Digitalmars-d wrote: > [...] >> Whenever I implement opAssign I have it return void and try to >> remember to propose that the compiler takes care of chained >> assignments by itself. >> >> Requiring user-defined assignment to `return *this;` was goofy in C++. >> Requiring user-defined assignment to `return this;` is goofy in D. >> Assignment should return void and the compiler should take care of it. > > +1. Is there an enhancement request for this? As Walter often says, if > it's not in bugzilla, it doesn't exist. ;-) https://issues.dlang.org/show_bug.cgi?id=21175 Not holding my breath. |
August 18, 2020 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tue, Aug 18, 2020 at 05:39:42PM -0400, Andrei Alexandrescu via Digitalmars-d wrote: [...] > https://issues.dlang.org/show_bug.cgi?id=21175 > > Not holding my breath. If someone can kick up a PR for this, the chances would increase significantly. ;-) T -- Error: Keyboard not attached. Press F1 to continue. -- Yoon Ha Lee, CONLANG |
March 24, 2021 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Saturday, 15 August 2020 at 04:28:05 UTC, mw wrote:
> // 7. atomic won't work
> core.atomic.atomicOp!"+="(s.sl, lb);
> //core.atomic.atomicOp!"+="(s.sL, cb); // Error: template instance core.atomic.atomicOp!("+=", Checked!(long, Abort), Checked!(long, Abort)) error instantiating
> //core.atomic.atomicFetchAdd(s.sL, cb); // Error: template core.atomic.atomicFetchAdd cannot deduce function from argument types !()(shared(Checked!(long, Abort)), Checked!(long, Abort)), candidates are:
> }
> ------------------------------------------------------------------------
I've been taking a crack at fixing some of these issue but I think `atomicOp` is incompatible with the premise of `Checked!T`. Either the Hook won't have the opportunity to intercept the update based on what the result would be or the update won't be atomic.
`atomicLoad`, `atomicStore`, and `cas` should be fine though as long as there is no Hook state.
|
March 24, 2021 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 18 August 2020 at 01:23:01 UTC, Andrei Alexandrescu wrote:
> Requiring user-defined assignment to `return *this;` was goofy in C++. Requiring user-defined assignment to `return this;` is goofy in D. Assignment should return void and the compiler should take care of it.
Do you mean the compiler should take care of returning *this when opAssign returns void? Because there are some use-cases for opAssign to return something different than `this`, but I cannot remember at the moment what it was. It's a niche case.
|
March 24, 2021 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Q. Schroll | On Wednesday, 24 March 2021 at 17:23:00 UTC, Q. Schroll wrote:
> On Tuesday, 18 August 2020 at 01:23:01 UTC, Andrei Alexandrescu wrote:
>> Requiring user-defined assignment to `return *this;` was goofy in C++. Requiring user-defined assignment to `return this;` is goofy in D. Assignment should return void and the compiler should take care of it.
>
> Do you mean the compiler should take care of returning *this when opAssign returns void? Because there are some use-cases for opAssign to return something different than `this`, but I cannot remember at the moment what it was. It's a niche case.
Ideally `lhs = rhs` would always evaluate to `lhs`, as it does for the built-in assignment operator. But that would require a deprecation cycle, since, as you say, existing code could be relying on the current behavior.
|
March 24, 2021 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Q. Schroll | On Wed, Mar 24, 2021 at 05:23:00PM +0000, Q. Schroll via Digitalmars-d wrote: > On Tuesday, 18 August 2020 at 01:23:01 UTC, Andrei Alexandrescu wrote: > > Requiring user-defined assignment to `return *this;` was goofy in C++. Requiring user-defined assignment to `return this;` is goofy in D. Assignment should return void and the compiler should take care of it. > > Do you mean the compiler should take care of returning *this when opAssign returns void? Because there are some use-cases for opAssign to return something different than `this`, but I cannot remember at the moment what it was. It's a niche case. I think Andrei meant that opAssign should *always* return void, and the compiler should always automatically make the RHS of `a = b;` its value. More precisely: struct S { ... } S a, b, c; return a = b = c; should be lowered to: struct S { ... } S a, b, c; b.opAssign(c); a.opAssign(b); return a; Having the value of `a = b` return anything other than the RHS of the assignment is goofy semantics. Since there is only one sensible meaning of `a = b = c`, the compiler should just automate it instead of requiring the user to restate the obvious (and potentially making a mistake or introducing goofy semantics that hurt the readability / maintainability of the resulting code). T -- If you're not part of the solution, you're part of the precipitate. |
March 24, 2021 Re: study: use checkedint as a drop-in replacement of native long | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Wednesday, 24 March 2021 at 17:38:14 UTC, H. S. Teoh wrote: > On Wed, Mar 24, 2021 at 05:23:00PM +0000, Q. Schroll via Digitalmars-d wrote: >> On Tuesday, 18 August 2020 at 01:23:01 UTC, Andrei Alexandrescu wrote: >> > Requiring user-defined assignment to `return *this;` was goofy in C++. Requiring user-defined assignment to `return this;` is goofy in D. Assignment should return void and the compiler should take care of it. >> >> Do you mean the compiler should take care of returning *this when opAssign returns void? Because there are some use-cases for opAssign to return something different than `this`, but I cannot remember at the moment what it was. It's a niche case. > > I think Andrei meant that opAssign should *always* return void, and the compiler should always automatically make the RHS of `a = b;` its value. More precisely: > > struct S { ... } > S a, b, c; > return a = b = c; > > should be lowered to: > > struct S { ... } > S a, b, c; > b.opAssign(c); > a.opAssign(b); > return a; > > Having the value of `a = b` return anything other than the RHS LHS I guess > of the assignment is goofy semantics. Since there is only one sensible meaning of `a = b = c`, the compiler should just automate it instead of requiring the user to restate the obvious (and potentially making a mistake or introducing goofy semantics that hurt the readability / maintainability of the resulting code). Does this expand to opIndexAssign and opIndexOpAssign? Because not returning by `ref` is common there and copying is not intended. What about property setters? It sure shouldn't implicitly call the getter -- and even if, a getter need not even exist. Enabling chained assignments isn't as trivial as fixing opAssign. I now know where I've seen an assignment operator not returning a reference to the object: C++'s slice_array and gslice_array[1] have void operator= and the reason probably is that (a) returning the (g)slice_array is conceptually wrong, (b) returning a valarray is wrong, too. Maybe there are constructs in D where the same reasoning applies. [1] https://www.cplusplus.com/reference/valarray/ |
Copyright © 1999-2021 by the D Language Foundation