www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Copy Constructor DIP

reply RazvanN <razvan.nitu1305 gmail.com> writes:
Hi everyone!

I managed to put together a first draft of the DIP for adding the 
copy constructor to the language [1]. If anyone is interested, 
please take a look. Suggestions and comments about technical 
aspects and wording are all welcome.

Thanks,
RazvanN

[1] https://github.com/dlang/DIPs/pull/129
Jul 10 2018
next sibling parent reply Guillaume Piolat <first.last gmail.com> writes:
On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding 
 the copy constructor to the language [1]. If anyone is 
 interested, please take a look. Suggestions and comments about 
 technical aspects and wording are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
Does it allow to remove the "T.init must always be valid for structs" rule?
Jul 10 2018
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, 10 July 2018 04:52:18 MDT Guillaume Piolat via Digitalmars-d 
wrote:
 On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding
 the copy constructor to the language [1]. If anyone is
 interested, please take a look. Suggestions and comments about
 technical aspects and wording are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
Does it allow to remove the "T.init must always be valid for structs" rule?
Why would it? init is the state of the object before any constructor runs, and quite a few things rely on it. The fact that we've allowed default initialization to be disabled already causes plenty of problems as it is. It's occasionally useful, but it definitely complicates things. D was designed with the idea that every type has an init value. What problem are you trying to solve here? - Jonathan M Davis
Jul 10 2018
parent reply Guillaume Piolat <first.last gmail.com> writes:
On Tuesday, 10 July 2018 at 11:58:53 UTC, Jonathan M Davis wrote:
 Does it allow to remove the "T.init must always be valid for 
 structs" rule?
Why would it? init is the state of the object before any constructor runs, and quite a few things rely on it. The fact that we've allowed default initialization to be disabled already causes plenty of problems as it is. It's occasionally useful, but it definitely complicates things. D was designed with the idea that every type has an init value. What problem are you trying to solve here? - Jonathan M Davis
None, I was just reacting to https://medium.com/ feepingcreature/d-structs-dont-work-for-domain-data-c09332349f43 Proper D structs almost require having a T.init that is valid, and in turn many public members may get to check for internal validity before doing things. This is in stark contrast to C++ where "proper" constructor is guaranteed so you don't check such validity. What is a "correct" T.init for a mutex RAII struct? It is a null handle value. It's obviously an invalid value for any purpose, but the D wrapper has to be a valid struct.
Jul 10 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, 10 July 2018 06:34:34 MDT Guillaume Piolat via Digitalmars-d 
wrote:
 On Tuesday, 10 July 2018 at 11:58:53 UTC, Jonathan M Davis wrote:
 Does it allow to remove the "T.init must always be valid for
 structs" rule?
Why would it? init is the state of the object before any constructor runs, and quite a few things rely on it. The fact that we've allowed default initialization to be disabled already causes plenty of problems as it is. It's occasionally useful, but it definitely complicates things. D was designed with the idea that every type has an init value. What problem are you trying to solve here? - Jonathan M Davis
None, I was just reacting to https://medium.com/ feepingcreature/d-structs-dont-work-for-domain-data-c0 9332349f43 Proper D structs almost require having a T.init that is valid, and in turn many public members may get to check for internal validity before doing things. This is in stark contrast to C++ where "proper" constructor is guaranteed so you don't check such validity. What is a "correct" T.init for a mutex RAII struct? It is a null handle value. It's obviously an invalid value for any purpose, but the D wrapper has to be a valid struct.
It's not necessarily expected that all of the functions on T.init are going to work. It's the stuff like copying it, assigning it, destroying it, etc. that have to work (and aside from destruction, you can even disable them if you need to). Not even toString actually needs to work. It's just that it's so common for folks to print values that it gets annoying when it doesn't work. And yes, if T.init does not match the invariant, then you can start running into problems, though it isn't necessarily fatal. Basically, in that case, you're forced to disable default initialization and avoid actually doing much with the init value. Honestly though, the reason that I think that invariants are terrible has nothing to do with T.init specifically but with opAssign. The invariant gets checked before opAssign, and in many cases, this makes sense, but in the case where you're doing something like void initialization or using emplace on uninitialized memory, it blows up in your face if the garbage that happened to be in the struct didn't match the invariant. The same would happen if T.init does not pass the invariant, but T.init isn't required to hit the problem. It's the fact that you can't bypass the invariant when giving the object a new value that's the main problem. If both assignment and copying worked without checking the invariant, then invariants would be a _lot_ more useful. Unfortunately, when I argued about this quite a bit with regards to opAssign several years ago, Walter didn't agree at all. He thought that it was critical that the invariant be valid when opAssign was called - and there are cases where that's arguably true - but since it doesn't work once you try to do fancier stuff like emplace, I'm of the opinion that invariants are unfortunately a waste of time - even without getting into the issue of init values. - Jonathan M Davis
Jul 10 2018
parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Tuesday, 10 July 2018 at 13:38:33 UTC, Jonathan M Davis wrote:
 He thought that it was critical that the invariant be valid 
 when opAssign was called - and there are cases where that's 
 arguably true - but since it doesn't work once you try to do 
 fancier stuff like emplace, I'm of the opinion that invariants 
 are unfortunately a waste of time - even without getting into 
 the issue of init values.

 - Jonathan M Davis
moveEmplace bypasses opAssign, since it memcopies directly. However, it resets its source value to T.init... so if T.init isn't valid, you simply crash whenever the source value goes out of scope. Using types with an invalid T.init feels like playing musical chairs with a crash. You can shuffle things around, and make some parts work, but *something* is always left crashing at the end.
Jul 10 2018
parent Uknown <sireeshkodali1 gmail.com> writes:
On Tuesday, 10 July 2018 at 14:28:09 UTC, FeepingCreature wrote:
 On Tuesday, 10 July 2018 at 13:38:33 UTC, Jonathan M Davis 
 wrote:
 [...]
Using types with an invalid T.init feels like playing musical chairs with a crash. You can shuffle things around, and make some parts work, but *something* is always left crashing at the end.
This is where I feel being able to redefine T.init would be useful, but as Andrei said, that is beyond the scope of this DIP
Jul 10 2018
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/10/2018 06:52 AM, Guillaume Piolat wrote:
 On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding the copy 
 constructor to the language [1]. If anyone is interested, please take 
 a look. Suggestions and comments about technical aspects and wording 
 are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
Does it allow to remove the "T.init must always be valid for structs" rule?
That's not part of this proposal's charter.
Jul 10 2018
prev sibling next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
I'm not keen on the added attribute.

Something along the lines of:

this(this; ref Foo foo) {}

might look a little better no?

And now no super special attribute to worry about parsing.
Jul 10 2018
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding the
 copy constructor to the language [1]. If anyone is interested,
 please take a look. Suggestions and comments about technical
 aspects and wording are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
I feel there's some things missing. 1. Explain the need and reasoning behind ` implicit`... that's weird and I don't like it at face value. 2. It looks like copy constructors are used to perform assignments (and not constructions)... but, there is also opAssign. What gives? Eg: S b = a; // <- copy construction? looks like an assignment. And not: S b = S(a); // <- actually looks like a construction, but this syntax seems to not be intended (and rightly so, it's pretty terrible) 3. In C++, copy constructors and copy assignment operators come in pairs (which is totally lame!), but we don't see that same pattern extend here, and it's not clear at all why. 4. Given the special rules where assignments are lifted to constructions, I want to know when that occurs (maybe that is already spec-ed wrt postblit?) - Manu
Jul 10 2018
next sibling parent reply RazvanN <razvan.nitu1305 gmail.com> writes:
On Tuesday, 10 July 2018 at 20:58:09 UTC, Manu wrote:
 On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding 
 the copy constructor to the language [1]. If anyone is 
 interested, please take a look. Suggestions and comments about 
 technical aspects and wording are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
I feel there's some things missing. 1. Explain the need and reasoning behind ` implicit`... that's weird
It is a simple way of defining a copy constructor without the need of adding new keywords and with minimal additions to the parser.
 and I don't like it at face value.
 2. It looks like copy constructors are used to perform 
 assignments
 (and not constructions)... but, there is also opAssign. What 
 gives?
     Eg:
       S b = a; // <- copy construction? looks like an 
 assignment.
     And not:
       S b = S(a); // <- actually looks like a construction, but 
 this
 syntax seems to not be intended (and rightly so, it's pretty 
 terrible)
 3. In C++, copy constructors and copy assignment operators come 
 in
 pairs (which is totally lame!), but we don't see that same 
 pattern
 extend here, and it's not clear at all why.
 4. Given the special rules where assignments are lifted to
 constructions, I want to know when that occurs (maybe that is 
 already
 spec-ed wrt postblit?)

 - Manu
Copy construction is used solely when the object was not initialized and it cannot be used otherwise. Consider this example: struct A { immutable int a = 7; implicit this(ref A another) { this.a = A.a; // first assignment over .init state - ok } void opAssign(A rhs) { this.a = rhs.a; } } void main() { A a = A(2); A b = a; // initialization -> calls copy constructor b = a; // cannot call copy constructor because it will // modify immutable; call opAssign. } The first assignment of b calls the copy constructor and the immutable field is initialized; later assignments to b.a will result in "modify immutable" error. The second assignment of b cannot call the copy constructor because it would then modify an initialized immutable field. However, with opAssign the compiler knows that A.a cannot be modified because it is immutable.
Jul 11 2018
parent reply Manu <turkeyman gmail.com> writes:
On Wed, 11 Jul 2018 at 00:40, RazvanN via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Tuesday, 10 July 2018 at 20:58:09 UTC, Manu wrote:
 On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding
 the copy constructor to the language [1]. If anyone is
 interested, please take a look. Suggestions and comments about
 technical aspects and wording are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
I feel there's some things missing. 1. Explain the need and reasoning behind ` implicit`... that's weird
It is a simple way of defining a copy constructor without the need of adding new keywords and with minimal additions to the parser.
What's wrong with: struct S { this(ref S copyFrom); } That looks like a perfectly good copy constructor declaration ;) I'm just saying, the DIP needs to explain this.
 and I don't like it at face value.
 2. It looks like copy constructors are used to perform
 assignments
 (and not constructions)... but, there is also opAssign. What
 gives?
     Eg:
       S b = a; // <- copy construction? looks like an
 assignment.
     And not:
       S b = S(a); // <- actually looks like a construction, but
 this
 syntax seems to not be intended (and rightly so, it's pretty
 terrible)
 3. In C++, copy constructors and copy assignment operators come
 in
 pairs (which is totally lame!), but we don't see that same
 pattern
 extend here, and it's not clear at all why.
 4. Given the special rules where assignments are lifted to
 constructions, I want to know when that occurs (maybe that is
 already
 spec-ed wrt postblit?)

 - Manu
Copy construction is used solely when the object was not initialized and it cannot be used otherwise. Consider this example: struct A { immutable int a = 7; implicit this(ref A another) { this.a = A.a; // first assignment over .init state - ok } void opAssign(A rhs) { this.a = rhs.a; } } void main() { A a = A(2); A b = a; // initialization -> calls copy constructor b = a; // cannot call copy constructor because it will // modify immutable; call opAssign. } The first assignment of b calls the copy constructor and the immutable field is initialized; later assignments to b.a will result in "modify immutable" error. The second assignment of b cannot call the copy constructor because it would then modify an initialized immutable field. However, with opAssign the compiler knows that A.a cannot be modified because it is immutable.
Right. This is all obvious and intuitive. What I'm hearing is that under this proposal, copy constructors and assignment operators DO come in pairs (just like in C++), but that's not mentioned here in this DIP. Since this proposal will introduce that recommended pattern from C++, it may be worth mentioning.
Jul 11 2018
next sibling parent reply RazvanN <razvan.nitu1305 gmail.com> writes:
 What's wrong with:
 struct S {
   this(ref S copyFrom);
 }

 That looks like a perfectly good copy constructor declaration 
 ;) I'm just saying, the DIP needs to explain this.
That is actually a valid constructor, according to today's compiler. There might be code out there that uses this syntax for the constructor and overnight it will be turned into a copy constructor. I agree that the current syntax is lacking. This was Andrei's proposition and I was initially against it, but he said to put it in the DIP so that we can discuss it as a community. Maybe this syntax is better: this(ref S a another) It looks like the c++ copy constructor but the ` ` makes it different from a constructor, so we're good. What do you think?
 Right. This is all obvious and intuitive.
 What I'm hearing is that under this proposal, copy constructors 
 and
 assignment operators DO come in pairs (just like in C++), but 
 that's
 not mentioned here in this DIP. Since this proposal will 
 introduce
 that recommended pattern from C++, it may be worth mentioning.
If by "come in pairs" you mean that you can define them both, then yes, that is the case. Will add a paragraph in the DIP to specify this. You mentioned that it's terrible that the assignment operator and the copy constructor come in pairs. Why is that? Would you rather have a copy constructor that is used also as an assignment operator?
Jul 11 2018
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2018 02:54 AM, RazvanN wrote:
 What's wrong with:
 struct S {
   this(ref S copyFrom);
 }

 That looks like a perfectly good copy constructor declaration ;) I'm 
 just saying, the DIP needs to explain this.
That is actually a valid constructor, according to today's compiler. There might be code out there that uses this syntax for the constructor and overnight it will be turned into a copy constructor. I agree that the current syntax is lacking. This was Andrei's proposition and I was initially against it, but he said to put it in the DIP so that we can discuss it as a community. Maybe this syntax is better: this(ref S a another) It looks like the c++ copy constructor but the ` ` makes it different from a constructor, so we're good. What do you think?
We will not add syntax if we can help it.
Jul 12 2018
parent reply Johannes Pfau <nospam example.com> writes:
Am Thu, 12 Jul 2018 09:48:37 -0400 schrieb Andrei Alexandrescu:

 I agree that the current syntax is lacking. This was Andrei's
 proposition and I was initially against it, but he said to put it in
 the DIP so that we can discuss it as a community. Maybe this syntax is
 better:
 
  this(ref S a another)
 
 It looks like the c++ copy constructor but the ` ` makes it different
 from a constructor, so we're good. What do you think?
We will not add syntax if we can help it.
We have this(this) for postblits so how about this(ref this a) for copy constructors? Unfortunately this is currently valid code and compiles: this is treated as typeof(this). However, we have already deprecated that, so maybe we can reuse the syntax? It should be a quite consistent evolution from this(this). (Another option is this(ref this A a) which does not conflict with existing syntax). -- Johannes
Jul 12 2018
parent Johannes Pfau <nospam example.com> writes:
Am Thu, 12 Jul 2018 17:32:06 +0000 schrieb Johannes Pfau:

 Am Thu, 12 Jul 2018 09:48:37 -0400 schrieb Andrei Alexandrescu:
 
 I agree that the current syntax is lacking. This was Andrei's
 proposition and I was initially against it, but he said to put it in
 the DIP so that we can discuss it as a community. Maybe this syntax is
 better:
 
  this(ref S a another)
 
 It looks like the c++ copy constructor but the ` ` makes it different
 from a constructor, so we're good. What do you think?
We will not add syntax if we can help it.
We have this(this) for postblits so how about this(ref this a) for copy constructors? Unfortunately this is currently valid code and compiles: this is treated as typeof(this). However, we have already deprecated that, so maybe we can reuse the syntax? It should be a quite consistent evolution from this(this). (Another option is this(ref this A a) which does not conflict with existing syntax).
I just read your other replies Andrei. I guess if we're ever going use the same syntax for implicit conversions, the implicit syntax is indeed consistent and logical. As long as it's only used for copy-ctors the name feels 'strange'. -- Johannes
Jul 12 2018
prev sibling next sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Thursday, 12 July 2018 at 06:54:37 UTC, RazvanN wrote:

 [...]
 If by "come in pairs" you mean that you can define them both, 
 then yes,
 that is the case. Will add a paragraph in the DIP to specify 
 this.

 You mentioned that it's terrible that the assignment operator
 and the copy constructor come in pairs. Why is that? Would you 
 rather
 have a copy constructor that is used also as an assignment 
 operator?
Because, like in C++, now you have to implement both and make sure they do the same thing. Boilerplaty and a recipe for disaster. Atila
Jul 12 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2018 09:49 AM, Atila Neves wrote:
 On Thursday, 12 July 2018 at 06:54:37 UTC, RazvanN wrote:
 
 [...]
 If by "come in pairs" you mean that you can define them both, then yes,
 that is the case. Will add a paragraph in the DIP to specify this.

 You mentioned that it's terrible that the assignment operator
 and the copy constructor come in pairs. Why is that? Would you rather
 have a copy constructor that is used also as an assignment operator?
Because, like in C++, now you have to implement both and make sure they do the same thing. Boilerplaty and a recipe for disaster. Atila
There's no meaningful way to avoid that. The two operations are fundamentally different, are typechecked differently, and actually are different in the presence of qualifiers on fields. Introspection is a key helper here compared to C++.
Jul 12 2018
parent reply Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 07:15, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 07/12/2018 09:49 AM, Atila Neves wrote:
 On Thursday, 12 July 2018 at 06:54:37 UTC, RazvanN wrote:

 [...]
 If by "come in pairs" you mean that you can define them both, then yes,
 that is the case. Will add a paragraph in the DIP to specify this.

 You mentioned that it's terrible that the assignment operator
 and the copy constructor come in pairs. Why is that? Would you rather
 have a copy constructor that is used also as an assignment operator?
Because, like in C++, now you have to implement both and make sure they do the same thing. Boilerplaty and a recipe for disaster. Atila
There's no meaningful way to avoid that. The two operations are fundamentally different, are typechecked differently, and actually are different in the presence of qualifiers on fields. Introspection is a key helper here compared to C++.
As I've said elsewhere, opAssign() can be fabricated by: this.destroy(); emplace(&this, copyFrom); We should consider fabricating an implicit assignment operator in the presence of an elaborate copy constructor. As you say, this interacts with qualifiers... I don't think it's trivial, but I think it should be explored. Otherwise whenever anyone forgets to implement an assignment operator, it'll just blit, which is almost certainly incorrect.
Jul 12 2018
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/18 6:37 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 07:15, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 07/12/2018 09:49 AM, Atila Neves wrote:
 On Thursday, 12 July 2018 at 06:54:37 UTC, RazvanN wrote:

 [...]
 If by "come in pairs" you mean that you can define them both, then yes,
 that is the case. Will add a paragraph in the DIP to specify this.

 You mentioned that it's terrible that the assignment operator
 and the copy constructor come in pairs. Why is that? Would you rather
 have a copy constructor that is used also as an assignment operator?
Because, like in C++, now you have to implement both and make sure they do the same thing. Boilerplaty and a recipe for disaster. Atila
There's no meaningful way to avoid that. The two operations are fundamentally different, are typechecked differently, and actually are different in the presence of qualifiers on fields. Introspection is a key helper here compared to C++.
As I've said elsewhere, opAssign() can be fabricated by: this.destroy(); emplace(&this, copyFrom);
Not if the object has immutable fields, is immutable itself, is assigned from an immutable object and has non-immutable indirections, etc. One issue the DIP is addressing carefully is copying across qualifier combinations. It also emphasizes how the current postblit fails at that.
 We should consider fabricating an implicit assignment operator in the
 presence of an elaborate copy constructor.
Not in this DIP.
 As you say, this interacts with qualifiers... I don't think it's
 trivial, but I think it should be explored. Otherwise whenever anyone
 forgets to implement an assignment operator, it'll just blit, which is
 almost certainly incorrect.
Exploring is of course welcome. Are you talking about the D language? Assignment never did just blit, and this DIP does not propose that. Andrei
Jul 12 2018
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Wed, 11 Jul 2018 at 23:55, RazvanN via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 What's wrong with:
 struct S {
   this(ref S copyFrom);
 }

 That looks like a perfectly good copy constructor declaration
 ;) I'm just saying, the DIP needs to explain this.
That is actually a valid constructor, according to today's compiler. There might be code out there that uses this syntax for the constructor and overnight it will be turned into a copy constructor.
Exactly. Is that a problem? It probably IS a copy constructor already, what else could it be? :)
 I agree that the current syntax is lacking. This was Andrei's
 proposition
 and I was initially against it, but he said to put it in the DIP
 so that
 we can discuss it as a community. Maybe this syntax is better:

  this(ref S a another)

 It looks like the c++ copy constructor but the ` ` makes it
 different from
 a constructor, so we're good. What do you think?
I would struggle to get behind anything other than `this(ref T)` 1. There's an extremely low probability such a function exists in any code, because it's redundant in the current language (postblit) 2. If it does exist, there's an extremely low probability that it's not already a valid copy constructor (what else could it possibly be?!) 3. The remaining cases are crazy. extremely^^2 low probability of causing an issue is not worth butchering the syntax for all time to come... if you ask me. Can the DIP identify a couple of trouble cases and present as motivation for the silly syntax? If no such cases can be identified, then it's hard to support an argument in favour.
 Right. This is all obvious and intuitive.
 What I'm hearing is that under this proposal, copy constructors
 and
 assignment operators DO come in pairs (just like in C++), but
 that's
 not mentioned here in this DIP. Since this proposal will
 introduce
 that recommended pattern from C++, it may be worth mentioning.
If by "come in pairs" you mean that you can define them both, then yes, that is the case. Will add a paragraph in the DIP to specify this.
Well, in C++ they SHOULD come in pairs. Things don't work if they don't, and I expect the same truth will emerge here. I'd like to see the DIP explore the parallel; understand why C++ specifies that they must come in pairs, and then explain that the same reasons also apply to D, or why they don't. Does dlang now have the 'rule-of-3' (or 5 now in c++11)?
 You mentioned that it's terrible that the assignment operator
 and the copy constructor come in pairs. Why is that? Would you
 rather
 have a copy constructor that is used also as an assignment
 operator?
It's pretty lame that C++ requires you to effectively write the same function twice in 2 different ways. It might be nice to explore if there's any way to unify them... I often define C++ assignment operators like this to save on code duplication: T& operator=(const T& rh) { this->~T(); new(this) T(rh); } I would hate to see this emerge as a pattern: void opAssign(ref T rh) { this.destroy(); emplace(&this, rh); } Being able to implement them both independently is *occasionally* useful, but 95% of the time, destruct + copy-construct is an equally efficient implementation for assignment. I'd suggest that this destruct+copy-construct pattern is a perfectly good substitute for assignment in most cases, and maybe the compiler should deploy the pattern as an implicit copy constructor in lieu of an explicit one? So, if the user specifies a complex copy constructor, but no assignment operator (which just blits on copy), then they've almost certainly introduced a bug on copying! Perhaps the compiler should automatically emit an assignment operator implemented as above in presence of a (suite of? [const/immutable/etc permutations]) 'complex' copy constructor?
Jul 12 2018
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/18 4:29 PM, Manu wrote:
 Being able to implement them both independently is*occasionally*
 useful, but 95% of the time, destruct + copy-construct is an equally
 efficient implementation for assignment. I'd suggest that this
 destruct+copy-construct pattern is a perfectly good substitute for
 assignment in most cases, and maybe the compiler should deploy the
 pattern as an implicit copy constructor in lieu of an explicit one?
 So, if the user specifies a complex copy constructor, but no
 assignment operator (which just blits on copy), then they've almost
 certainly introduced a bug on copying! Perhaps the compiler should
 automatically emit an assignment operator implemented as above in
 presence of a (suite of? [const/immutable/etc permutations]) 'complex'
 copy constructor?
Not the charter of the current DIP.
Jul 12 2018
parent reply Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 18:25, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 7/12/18 4:29 PM, Manu wrote:
 Being able to implement them both independently is*occasionally*
 useful, but 95% of the time, destruct + copy-construct is an equally
 efficient implementation for assignment. I'd suggest that this
 destruct+copy-construct pattern is a perfectly good substitute for
 assignment in most cases, and maybe the compiler should deploy the
 pattern as an implicit copy constructor in lieu of an explicit one?
 So, if the user specifies a complex copy constructor, but no
 assignment operator (which just blits on copy), then they've almost
 certainly introduced a bug on copying! Perhaps the compiler should
 automatically emit an assignment operator implemented as above in
 presence of a (suite of? [const/immutable/etc permutations]) 'complex'
 copy constructor?
Not the charter of the current DIP.
In a post-blit world, with no opAssign specified, postblit will call for copy construction AND for assignment, thereby assignment is always correct. Once postblit is swapped for a copy-constructor, absence of opAssign will result in invalid behaviour on assignment. Introduction of copy constructor breaks default assignment, it needs to address it somehow. I think my suggestion is the only practical solution.
Jul 12 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/18 10:05 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 18:25, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 7/12/18 4:29 PM, Manu wrote:
 Being able to implement them both independently is*occasionally*
 useful, but 95% of the time, destruct + copy-construct is an equally
 efficient implementation for assignment. I'd suggest that this
 destruct+copy-construct pattern is a perfectly good substitute for
 assignment in most cases, and maybe the compiler should deploy the
 pattern as an implicit copy constructor in lieu of an explicit one?
 So, if the user specifies a complex copy constructor, but no
 assignment operator (which just blits on copy), then they've almost
 certainly introduced a bug on copying! Perhaps the compiler should
 automatically emit an assignment operator implemented as above in
 presence of a (suite of? [const/immutable/etc permutations]) 'complex'
 copy constructor?
Not the charter of the current DIP.
In a post-blit world, with no opAssign specified, postblit will call for copy construction AND for assignment, thereby assignment is always correct. Once postblit is swapped for a copy-constructor, absence of opAssign will result in invalid behaviour on assignment. Introduction of copy constructor breaks default assignment, it needs to address it somehow. I think my suggestion is the only practical solution.
Affirmative. The DIP needs to specify how assignment is handled if no opAssign is present but a copy ctor is present. Thanks!
Jul 12 2018
parent reply RazvanN <razvan.nitu1305 gmail.com> writes:
 In a post-blit world, with no opAssign specified, postblit 
 will call
 for copy construction AND for assignment, thereby assignment 
 is always
 correct.
 Once postblit is swapped for a copy-constructor, absence of 
 opAssign
 will result in invalid behaviour on assignment.
Indeed, but this was the source of the problem also, because you could modify immutable fields that way.
 Introduction of copy constructor breaks default assignment, it 
 needs
 to address it somehow. I think my suggestion is the only 
 practical
 solution.
Affirmative. The DIP needs to specify how assignment is handled if no opAssign is present but a copy ctor is present. Thanks!
The difference between a copy constructor and opAssign is how the type checking is performed. This leads to situations where a copy constructor is not suitable as an assignment operator. However, if a copy constructor is defined in a way that is correctly type checked both as a constructor and as a normal function, then there is no problem in using the copy constructor for assignments: struct A { immutable int b; int c; implicit this(ref A rhs) { this.c = rhs.c; } } struct B { immutable int b; int c; implicit this(ref A rhs) { this.b = rhs.b; this.c = rhs.c; } } void main() { A a, c; A b = a; b = c; // no problem in calling copy constructor, immutable is // not modified B d, e; B f = d; f = d; // cannot use copy constructor because it will modify immutable // field B.b; for this situation you need an opAssign to specify // how the assignment is dealt with. } The problem with this approach is that some copy constructors will also be used as assignment operators while others will not, but with good error messages it could be handled (error on line `f = d` : opAssign not specified and the copy constructor is not suitable for assignments because it modifies immutable field `b`). What are your opinions on this?
Jul 13 2018
next sibling parent RazvanN <razvan.nitu1305 gmail.com> writes:
The above code contains a typo. The parameter type of the second 
copy constructor is meant to be B not A
Jul 13 2018
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On Fri, 13 Jul 2018 at 04:05, RazvanN via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 [...]
The problem with this approach is that some copy constructors will also be used as assignment operators while others will not, but with good error messages it could be handled (error on line `f = d` : opAssign not specified and the copy constructor is not suitable for assignments because it modifies immutable field `b`). What are your opinions on this?
Right; I figure, if the struct contains members that can't be copied, then the struct is defined in such a way that it simply can't be copied. I mean, if the copy constructor can't be used to copy the thing, then is copying the struct valid at all? What would a valid copy operation on a struct with an immutable field do? Either way, in that case, a good error should inform the user they need to write an explicit opAssign.
Jul 13 2018
prev sibling parent sclytrack <fake hotmail.com> writes:
On Friday, 13 July 2018 at 11:02:57 UTC, RazvanN wrote:
 [...]
Indeed, but this was the source of the problem also, because you could modify immutable fields that way.
 [...]
Affirmative. The DIP needs to specify how assignment is handled if no opAssign is present but a copy ctor is present. Thanks!
The difference between a copy constructor and opAssign is how the type checking is performed. This leads to situations where a copy constructor is not suitable as an assignment operator. However, if a copy
...
 What are your opinions on this?
What about going the other way? Can you use the unqualified opAssign as the unqualified copy constructor? I assume these implicit copy constructors are normal constructors.
Jul 15 2018
prev sibling parent meppl <mephisto nordhoff-online.de> writes:
On Thursday, 12 July 2018 at 20:29:43 UTC, Manu wrote:
 On Wed, 11 Jul 2018 at 23:55, RazvanN via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 What's wrong with:
 struct S {
   this(ref S copyFrom);
 }

 That looks like a perfectly good copy constructor 
 declaration ;) I'm just saying, the DIP needs to explain 
 this.
That is actually a valid constructor, according to today's compiler. There might be code out there that uses this syntax for the constructor and overnight it will be turned into a copy constructor.
Exactly. Is that a problem? It probably IS a copy constructor already, what else could it be? :)
it can be something else. For example a lifo list pusher. Even if it is considered bad design, someone might have done it
Jul 13 2018
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/11/2018 05:28 PM, Manu wrote:
 What's wrong with:
 struct S {
    this(ref S copyFrom);
 }
 
 That looks like a perfectly good copy constructor declaration ;)
 I'm just saying, the DIP needs to explain this.
Thanks, worth a paragraph discussing silent semantics change.
 Right. This is all obvious and intuitive.
 What I'm hearing is that under this proposal, copy constructors and
 assignment operators DO come in pairs (just like in C++), but that's
 not mentioned here in this DIP. Since this proposal will introduce
 that recommended pattern from C++, it may be worth mentioning.
Shouldn't hurt to add 1-2 sentences to the effect. (Also an example.)
Jul 12 2018
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/10/2018 04:58 PM, Manu wrote:
 On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding the
 copy constructor to the language [1]. If anyone is interested,
 please take a look. Suggestions and comments about technical
 aspects and wording are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
I feel there's some things missing. 1. Explain the need and reasoning behind ` implicit`.
Razvan: I think it would help to explain that the attribute is necessary to avoid changing semantics of existing code. Thanks.
 3. In C++, copy constructors and copy assignment operators come in
 pairs (which is totally lame!), but we don't see that same pattern
 extend here, and it's not clear at all why.
The proposal does not affect or interfere with opAssign in any way.
 4. Given the special rules where assignments are lifted to
 constructions, I want to know when that occurs (maybe that is already
 spec-ed wrt postblit?)
What special rules are you referring to? Thanks.
Jul 12 2018
parent reply ag0aep6g <anonymous example.com> writes:
On 07/12/2018 03:40 PM, Andrei Alexandrescu wrote:
 On 07/10/2018 04:58 PM, Manu wrote:
[...]
 1. Explain the need and reasoning behind ` implicit`.
Razvan: I think it would help to explain that the attribute is necessary to avoid changing semantics of existing code. Thanks.
You're still potentially changing the semantics of existing code. ` implicit` can be a UDA today: ---- enum implicit = 0; struct C { implicit this(ref C another) {} } ---- Today, that's a normal constructor. With the DIP, it becomes a copy constructor.
Jul 12 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/18 2:30 PM, ag0aep6g wrote:
 On 07/12/2018 03:40 PM, Andrei Alexandrescu wrote:
 On 07/10/2018 04:58 PM, Manu wrote:
[...]
 1. Explain the need and reasoning behind ` implicit`.
Razvan: I think it would help to explain that the attribute is necessary to avoid changing semantics of existing code. Thanks.
You're still potentially changing the semantics of existing code. ` implicit` can be a UDA today: ---- enum implicit = 0; struct C {     implicit this(ref C another) {} } ---- Today, that's a normal constructor. With the DIP, it becomes a copy constructor.
That is correct and a liability of the current DIP. That should be mentioned in it.
Jul 12 2018
parent reply Jacob Carlborg <doob me.com> writes:
On Friday, 13 July 2018 at 01:18:48 UTC, Andrei Alexandrescu 
wrote:
 On 7/12/18 2:30 PM, ag0aep6g wrote:
 You're still potentially changing the semantics of existing 
 code. ` implicit` can be a UDA today:
 
 ----
 enum implicit = 0;
 struct C
 {
       implicit this(ref C another) {}
 }
 ----
 
 Today, that's a normal constructor. With the DIP, it becomes a 
 copy constructor.
That is correct and a liability of the current DIP. That should be mentioned in it.
That's easily fixed by implementing a compiler recognized UDA. That would mean that it would only be a copy constructor if "implicit" is defined in core.attribute. This would also avoid any special syntax in the parser. The already existing selector is implemented like this. -- /Jacob Carlborg
Jul 14 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 7/14/18 11:26 AM, Jacob Carlborg wrote:
 On Friday, 13 July 2018 at 01:18:48 UTC, Andrei Alexandrescu wrote:
 On 7/12/18 2:30 PM, ag0aep6g wrote:
 You're still potentially changing the semantics of existing code. 
 ` implicit` can be a UDA today:

 ----
 enum implicit = 0;
 struct C
 {
       implicit this(ref C another) {}
 }
 ----

 Today, that's a normal constructor. With the DIP, it becomes a copy 
 constructor.
That is correct and a liability of the current DIP. That should be mentioned in it.
That's easily fixed by implementing a compiler recognized UDA. That would mean that it would only be a copy constructor if "implicit" is defined in core.attribute. This would also avoid any special syntax in the parser. The already existing selector is implemented like this.
Affirmative. We're going that route, similar to " safe" and " nogc".
Jul 16 2018
parent reply ag0aep6g <anonymous example.com> writes:
On 07/16/2018 09:06 PM, Andrei Alexandrescu wrote:
 On 7/14/18 11:26 AM, Jacob Carlborg wrote:
[...]
 That's easily fixed by implementing a compiler recognized UDA. That 
 would mean that it would only be a copy constructor if "implicit" is 
 defined in core.attribute. This would also avoid any special syntax in 
 the parser. The already existing  selector is implemented like this.
Affirmative. We're going that route, similar to " safe" and " nogc".
safe and nogc are not compiler recognized UDAs. If you implement implicit like them, then you're not doing what Jacob suggests.
Jul 16 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/16/18 3:12 PM, ag0aep6g wrote:
 On 07/16/2018 09:06 PM, Andrei Alexandrescu wrote:
 On 7/14/18 11:26 AM, Jacob Carlborg wrote:
[...]
 That's easily fixed by implementing a compiler recognized UDA. That 
 would mean that it would only be a copy constructor if "implicit" is 
 defined in core.attribute. This would also avoid any special syntax 
 in the parser. The already existing  selector is implemented like this.
Affirmative. We're going that route, similar to " safe" and " nogc".
safe and nogc are not compiler recognized UDAs. If you implement implicit like them, then you're not doing what Jacob suggests.
Then "negative" :o). In brief implicit follows the same implementation as safe and nogc/
Jul 16 2018
parent reply Jacob Carlborg <doob me.com> writes:
On Tuesday, 17 July 2018 at 00:04:12 UTC, Andrei Alexandrescu 
wrote:

 Then "negative" :o). In brief  implicit follows the same 
 implementation as  safe and  nogc/
Why? This is a breaking change. Why not go with an approach that does not cause any breaking changes, which is just as easy to do? It also doesn't required any special casing in the parser. This is how selector is implemented. -- /Jacob Carlborg
Jul 17 2018
parent reply aliak00 <something something.com> writes:
On Tuesday, 17 July 2018 at 07:27:32 UTC, Jacob Carlborg wrote:
 On Tuesday, 17 July 2018 at 00:04:12 UTC, Andrei Alexandrescu 
 wrote:

 Then "negative" :o). In brief  implicit follows the same 
 implementation as  safe and  nogc/
Why? This is a breaking change. Why not go with an approach that does not cause any breaking changes, which is just as easy to do? It also doesn't required any special casing in the parser. This is how selector is implemented. -- /Jacob Carlborg
Can you explain a bit more here? How does having implicit as a compiler recognized UDA avoid breaking changes as opposed to it being implemented like nogc/ safe (how are those implemented differently anyway?) Cheers, - Ali
Jul 17 2018
parent reply ag0aep6g <anonymous example.com> writes:
On 07/17/2018 03:03 PM, aliak00 wrote:
 Can you explain a bit more here? How does having implicit as a compiler 
 recognized UDA avoid breaking changes as opposed to it being implemented 
 like  nogc/ safe (how are those implemented differently anyway?)
In a UDA ` implicit`, `implicit` is just a normal symbol. So the normal lookup rules apply. In particular, you can shadow an imported `implicit` with a local one: --- object.d enum implicit = 1; /* Actual implementation would be different. */ --- bar.d /* invisible default `import object` here */ implicit void f() {} static assert(__traits(getAttributes, f)[0] == 1); /* Passes. `object.implicit` is used. */ --- baz.d /* invisible default `import object` here */ enum implicit = 2; implicit void f() {} static assert(__traits(getAttributes, f)[0] == 2); /* Passes. The local `implicit` is used. */ You can't do that with ` safe`, because ` safe` is not a UDA, and `safe` is not a symbol there. ` safe` is special syntax, recognized as a whole by the parser. No symbol lookup is happening. You can see the difference if you change all occurrences of "implicit" to "safe" in that code. Won't work. As for breakage, baz.d is working code today. With ` implicit` as a UDA, it keeps working in the same way. With ` implicit` as a new non-UDA attribute, it will change its meaning, and the assert will fail.
Jul 17 2018
parent aliak00 <something something.com> writes:
On Tuesday, 17 July 2018 at 14:41:06 UTC, ag0aep6g wrote:
 On 07/17/2018 03:03 PM, aliak00 wrote:
 [...]
In a UDA ` implicit`, `implicit` is just a normal symbol. So the normal lookup rules apply. In particular, you can shadow an imported `implicit` with a local one: [...]
Ah, gotcha! Thank you!
Jul 17 2018
prev sibling next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
 2. It looks like copy constructors are used to perform assignments
 (and not constructions)... but, there is also opAssign. What gives?
     Eg:
       S b = a; // <- copy construction? looks like an assignment.
     And not:
       S b = S(a); // <- actually looks like a construction, but this
 syntax seems to not be intended (and rightly so, it's pretty terrible)
S b = a; has never been assignment in either C++ or D. It's initialization / construction, which means that it calls a constructor - be that a postblit constructor or a copy constructor. Assignment only occurs when you're giving an existing object a new value. And why would S b = S(a); not be intended? Sure, it's kind of pointless if a is an S, but if you have a copy constructor, it makes perfect sense that S(a) would work and would be pretty bizarre if it didn't, since it's explicitly calling the copy constructor. It even works right now if you give S a constructor that takes an S. It just isn't actually treated as a proper copy constructor at the moment, since that's currently the postblit constructor's job. - Jonathan M Davis
Jul 10 2018
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On Tue, 10 Jul 2018 at 15:23, Jonathan M Davis via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
 2. It looks like copy constructors are used to perform assignments
 (and not constructions)... but, there is also opAssign. What gives?
     Eg:
       S b = a; // <- copy construction? looks like an assignment.
     And not:
       S b = S(a); // <- actually looks like a construction, but this
 syntax seems to not be intended (and rightly so, it's pretty terrible)
S b = a; has never been assignment in either C++ or D. It's initialization / construction, which means that it calls a constructor - be that a postblit constructor or a copy constructor. Assignment only occurs when you're giving an existing object a new value.
I know this, but it's not syntactically obvious, it just depends on the fact that you already know that fact... I feel a DIP about copy construction needs to have some text explaining that, and where the edges are. Is an initialisation assignment can use a copy constructor, why can't a normal assignment implicitly use a copy constructor? (implicit destruct then copy-construct)
 And why would

 S b = S(a);

 not be intended? Sure, it's kind of pointless if a is an S, but if you have
 a copy constructor, it makes perfect sense that S(a) would work and would be
 pretty bizarre if it didn't, since it's explicitly calling the copy
 constructor.
But there's a super explicit ` implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and ` implicit` is a lie?
 It even works right now if you give S a constructor that takes
 an S. It just isn't actually treated as a proper copy constructor at the
 moment, since that's currently the postblit constructor's job.
Current language doesn't have ` implicit` written anywhere...
Jul 10 2018
next sibling parent reply RazvanN <razvan.nitu1305 gmail.com> writes:
 But there's a super explicit ` implicit` thing written right 
 there... so should we expect that an *explicit* call to the 
 copy constructor is not allowed? Or maybe it is allowed and 
 ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
Jul 11 2018
next sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right 
 there... so should we expect that an *explicit* call to the 
 copy constructor is not allowed? Or maybe it is allowed and 
 ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
How is this different from other types of constructors or destructors? I also very much dislike the syntax - it makes no sense to me at all. I commented on the PR itself asking why it differs so much from C++ - specifically, what's bad about the C++ way of doing things there that we want to avoid? Atila
Jul 11 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/11/2018 11:11 AM, Atila Neves wrote:
 On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right there... 
 so should we expect that an *explicit* call to the copy constructor 
 is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
How is this different from other types of constructors or destructors?
The main difference is that the compiler may insert calls to it implicitly.
 I also very much dislike the syntax - it makes no sense to me at all. I 
 commented on the PR itself asking why it differs so much from C++ - 
 specifically, what's bad about the C++ way of doing things there that we 
 want to avoid?
C++ is at the other end of the spectrum - constructors are too implicit, so the "explicit" keyword has been introduced with the advice to use it in the vast majority of cases. If C++ could do it again, it would make everything explicit and add an "implicit" keyword.
Jul 12 2018
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, 12 July 2018 07:45:30 MDT Andrei Alexandrescu via Digitalmars-d 
wrote:
 I also very much dislike the syntax - it makes no sense to me at all. I
 commented on the PR itself asking why it differs so much from C++ -
 specifically, what's bad about the C++ way of doing things there that we
 want to avoid?
C++ is at the other end of the spectrum - constructors are too implicit, so the "explicit" keyword has been introduced with the advice to use it in the vast majority of cases. If C++ could do it again, it would make everything explicit and add an "implicit" keyword.
That's only an issue in C++, because C++ uses constructors for implicit conversions unless you mark them with explicit. D doesn't ever do implicit conversions like that. All constructors are effectively explicit. Is this DIP proposing that we add such implicit conversions? Because if it is, that's a pretty major change that arguably has nothing to do with copy constructors, since copy constructors are for constructing an object from another object of the same type (though possibly of different mutability), not from objects of other types. That would just be a normal constructor. I really don't understand what the purpose of implicit is here. What's the problem of just going off of the type of the constructor's single parameter to determine whether it's a copy constructor? - Jonathan M Davis
Jul 12 2018
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2018 10:54 AM, Jonathan M Davis wrote:
 On Thursday, 12 July 2018 07:45:30 MDT Andrei Alexandrescu via Digitalmars-d
 wrote:
 I also very much dislike the syntax - it makes no sense to me at all. I
 commented on the PR itself asking why it differs so much from C++ -
 specifically, what's bad about the C++ way of doing things there that we
 want to avoid?
C++ is at the other end of the spectrum - constructors are too implicit, so the "explicit" keyword has been introduced with the advice to use it in the vast majority of cases. If C++ could do it again, it would make everything explicit and add an "implicit" keyword.
That's only an issue in C++, because C++ uses constructors for implicit conversions unless you mark them with explicit. D doesn't ever do implicit conversions like that. All constructors are effectively explicit. Is this DIP proposing that we add such implicit conversions?
The DIP is proposing what's in the DIP :o). We actually clarify this in text: "The type of the parameter to the copy constructor needs to be identical to typeof(this); an error is issued otherwise. This requirement may be relaxed in the future in order to accomodate implicit copying from objects of a different type:" [example follows]
 I really don't understand what the purpose of  implicit is here. What's the
 problem of just going off of the type of the constructor's single parameter
 to determine whether it's a copy constructor?
That would silently change semantics of existing code, which is to be avoided. Andrei
Jul 12 2018
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 07/11/2018 11:11 AM, Atila Neves wrote:
 On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right there...
 so should we expect that an *explicit* call to the copy constructor
 is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
How is this different from other types of constructors or destructors?
The main difference is that the compiler may insert calls to it implicitly.
You mean like ~this(), and op[Anything](), and front() and popFront() and empty()? I don't think we need this attribute.
Jul 12 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/18 6:34 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 07/11/2018 11:11 AM, Atila Neves wrote:
 On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right there...
 so should we expect that an *explicit* call to the copy constructor
 is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
How is this different from other types of constructors or destructors?
The main difference is that the compiler may insert calls to it implicitly.
You mean like ~this(), and op[Anything](), and front() and popFront() and empty()? I don't think we need this attribute.
I mentioned this, and patiently will mention it again: we need to introduce the attribute so as to avoid silently changing the semantics of existing code.
Jul 12 2018
parent reply Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 19:15, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 7/12/18 6:34 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 07/11/2018 11:11 AM, Atila Neves wrote:
 On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right there...
 so should we expect that an *explicit* call to the copy constructor
 is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
How is this different from other types of constructors or destructors?
The main difference is that the compiler may insert calls to it implicitly.
You mean like ~this(), and op[Anything](), and front() and popFront() and empty()? I don't think we need this attribute.
I mentioned this, and patiently will mention it again: we need to introduce the attribute so as to avoid silently changing the semantics of existing code.
Take this reply while assuming a no- implicit world, which I think is still a reasonable option (although I support introduction of implicit in my other recent replies): Don't be condescending. I asked, and I will "patiently" ask again, What existing code are you changing the semantics of? It's still not clear to me how accepting `this(ref T)` as a magic signature that is a copy constructor can break existing code? Is it the unlikely^^2 case that the function exists somewhere and doesn't perform copy construction? 1. the function is highly unlikely to exist because postblit; it's a meaningless function to write. are there any known instances of that signature in the wild? 2. if the function does exist, it's highly unlikely that it doesn't perform a valid copy construction; what else could it possibly do? 3. remaining cases are broken by this DIP, but they are probably crazy and deserve to be deprecated! Is there any reasonable existing use of the signature that would be legitimately broken by being invoked implicitly? I feel like there's something that I'm missing... but if there's not, then just change the semantic. I reason; copy construction is something so fundamental. It will be written by basically every programmer with relative high frequently, and adding awkward syntax or weird language baggage to the concept feels like a very poor choice. By contrast, if there's 1 user out there who used the copy-constructor signature to do some weird thing other than copy construction, and their code is broken by this change, his use case does not balance the imposition applied to every implementation of copy constructor forever from this time forward. This is so much more important than that, it's extremely fundamental language stuff, and needs to be as friction-less as possible, and it should certainly not reek of legacy drama.
Jul 12 2018
next sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
 On Thu, 12 Jul 2018 at 19:15, Andrei Alexandrescu via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On 7/12/18 6:34 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:

[..] doesn't perform copy construction? 1. the function is highly unlikely to exist because postblit; it's a meaningless function to write. are there any known instances of that signature in the wild?
https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis. Atila
Jul 13 2018
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 7/13/18 8:31 AM, Atila Neves wrote:
 On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
 On Thu, 12 Jul 2018 at 19:15, Andrei Alexandrescu via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 On 7/12/18 6:34 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via > 
Digitalmars-d <digitalmars-d puremagic.com> wrote:

[..] doesn't perform copy construction?   1. the function is highly unlikely to exist because postblit; it's a meaningless function to write. are there any known instances of that signature in the wild?
https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.
A proposal that just works without any user intervention would definitely be attractive. The drawback is silent modification of code behavior. Consider: import std.stdio; struct A { this(ref immutable A obj) { writeln("x"); } } void main() { immutable A a1; A a2 = A(a1); A a3 = a1; } With the current language, "x" is printed once. If we make the ctor implicit, "x" is printed twice. In the "levels of hell" of semantics changes, probably the nicest is allowing code to compile that previously didn't. Then, refusing to compile code that previously did would be definitely bad. But if you want to drink the cup of disgrace to the bottom, you must reach for silent change of behavior.
Jul 13 2018
parent reply Atila Neves <atila.neves gmail.com> writes:
On Friday, 13 July 2018 at 14:12:59 UTC, Andrei Alexandrescu 
wrote:
 On 7/13/18 8:31 AM, Atila Neves wrote:
 On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
 [...]
https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.
A proposal that just works without any user intervention would definitely be attractive. The drawback is silent modification of code behavior. Consider: import std.stdio; struct A { this(ref immutable A obj) { writeln("x"); } } void main() { immutable A a1; A a2 = A(a1); A a3 = a1; } With the current language, "x" is printed once. If we make the ctor implicit, "x" is printed twice. In the "levels of hell" of semantics changes, probably the nicest is allowing code to compile that previously didn't. Then, refusing to compile code that previously did would be definitely bad. But if you want to drink the cup of disgrace to the bottom, you must reach for silent change of behavior.
I agree on the levels of hell. I wasn't aware the kind of change above would happen - methinks it should be in the DIP. I think I now even understand why ` implicit` is there to begin with. I still think it's confusing, so imagine someone new to the language. Atila
Jul 13 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 7/13/18 11:14 AM, Atila Neves wrote:
 On Friday, 13 July 2018 at 14:12:59 UTC, Andrei Alexandrescu wrote:
 On 7/13/18 8:31 AM, Atila Neves wrote:
 On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
 [...]
https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.
A proposal that just works without any user intervention would definitely be attractive. The drawback is silent modification of code behavior. Consider: import std.stdio; struct A {     this(ref immutable A obj) { writeln("x"); } } void main() {     immutable A a1;     A a2 = A(a1);     A a3 = a1; } With the current language, "x" is printed once. If we make the ctor implicit, "x" is printed twice. In the "levels of hell" of semantics changes, probably the nicest is allowing code to compile that previously didn't. Then, refusing to compile code that previously did would be definitely bad. But if you want to drink the cup of disgrace to the bottom, you must reach for silent change of behavior.
I agree on the levels of hell. I wasn't aware the kind of change above would happen - methinks it should be in the DIP.
Great. Razvan, can you please add this example with discussion to the DIP (probably at the end of the Motivation section as an explanation why we need the addition of implicit). Thanks.
 I think I now even understand why ` implicit` is there to begin with. I 
 still think it's confusing, so imagine someone new to the language.
Interesting. Coming from a C++ background makes the matter obvious because there's plenty of implicit vs. explicit discussion. To compensate for my bias - what do you think would be a better attribute name? Andrei
Jul 13 2018
next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Friday, 13 July 2018 at 16:02:51 UTC, Andrei Alexandrescu 
wrote:
 On 7/13/18 11:14 AM, Atila Neves wrote:
 [...]
Great. Razvan, can you please add this example with discussion to the DIP (probably at the end of the Motivation section as an explanation why we need the addition of implicit). Thanks.
 [...]
Interesting. Coming from a C++ background makes the matter obvious because there's plenty of implicit vs. explicit discussion. To compensate for my bias - what do you think would be a better attribute name? Andrei
Why " implicit" is an attribute and not a keyword? -Alexander
Jul 13 2018
prev sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Friday, 13 July 2018 at 16:02:51 UTC, Andrei Alexandrescu 
wrote:
 On 7/13/18 11:14 AM, Atila Neves wrote:
 On Friday, 13 July 2018 at 14:12:59 UTC, Andrei Alexandrescu 
 wrote:
 On 7/13/18 8:31 AM, Atila Neves wrote:
 On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
 [...]
https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.
A proposal that just works without any user intervention would definitely be attractive. The drawback is silent modification of code behavior. Consider: import std.stdio; struct A {     this(ref immutable A obj) { writeln("x"); } } void main() {     immutable A a1;     A a2 = A(a1);     A a3 = a1; } With the current language, "x" is printed once. If we make the ctor implicit, "x" is printed twice. In the "levels of hell" of semantics changes, probably the nicest is allowing code to compile that previously didn't. Then, refusing to compile code that previously did would be definitely bad. But if you want to drink the cup of disgrace to the bottom, you must reach for silent change of behavior.
I agree on the levels of hell. I wasn't aware the kind of change above would happen - methinks it should be in the DIP.
Great. Razvan, can you please add this example with discussion to the DIP (probably at the end of the Motivation section as an explanation why we need the addition of implicit). Thanks.
 I think I now even understand why ` implicit` is there to 
 begin with. I still think it's confusing, so imagine someone 
 new to the language.
Interesting. Coming from a C++ background makes the matter obvious because there's plenty of implicit vs. explicit discussion. To compensate for my bias - what do you think would be a better attribute name?
I came to D via C++ as well. Maybe my brain short-circuited because I saw `A a3 = a1;` in a discussion about copy constructors and assumed it would be called, and didn't realise it wouldn't have been before. I just took for granted the implicitness of the constructor call, since that's what C++ does! I wasn't even aware one could declare a C++ copy constructor `explicit` until I tried it just now. It's just not something I've ever thought about. Now that I understand the implicit call ` implicit` makes sense to me but I'm convinced it'll confuse more people than not. I'll see if I can come up with a better name. Atila
Jul 13 2018
parent reply Manu <turkeyman gmail.com> writes:
On Fri, 13 Jul 2018 at 10:35, Atila Neves via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 [...]

 Now that I understand the implicit call ` implicit` makes sense
 to me but I'm convinced it'll confuse more people than not. I'll
 see if I can come up with a better name.
You don't find 'implicit' satisfactory as an obvious and intuitive complement to 'explicit' in C++? I think the name's perfect, but I need to know it works in general to find it acceptable. As a marker used in this one case, it's a terrible name, as a generalised concept, it's perfect.
Jul 13 2018
parent =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Friday, 13 July 2018 at 18:54:48 UTC, Manu wrote:
 As a marker used in this one case, it's a terrible name, as a
 generalised concept, it's perfect.
Exactly.
Jul 13 2018
prev sibling parent reply aliak <something something.com> writes:
On Friday, 13 July 2018 at 12:31:41 UTC, Atila Neves wrote:
 On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
 On Thu, 12 Jul 2018 at 19:15, Andrei Alexandrescu via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On 7/12/18 6:34 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:

[..] doesn't perform copy construction? 1. the function is highly unlikely to exist because postblit; it's a meaningless function to write. are there any known instances of that signature in the wild?
https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis. Atila
https://www.google.no/search?q=allintext%3A+%22this%28ref%22+site%3Agithub.com+filetype%3Ad&oq=allintext%3A+%22this%28ref%22+site%3Agithub.com+filetype%3Ad
Jul 17 2018
parent Manu <turkeyman gmail.com> writes:
On Tue, 17 Jul 2018 at 10:20, aliak via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Friday, 13 July 2018 at 12:31:41 UTC, Atila Neves wrote:
 On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
 On Thu, 12 Jul 2018 at 19:15, Andrei Alexandrescu via
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On 7/12/18 6:34 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via
 Digitalmars-d <digitalmars-d puremagic.com> wrote:

[..] doesn't perform copy construction? 1. the function is highly unlikely to exist because postblit; it's a meaningless function to write. are there any known instances of that signature in the wild?
https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis. Atila
https://www.google.no/search?q=allintext%3A+%22this%28ref%22+site%3Agithub.com+filetype%3Ad&oq=allintext%3A+%22this%28ref%22+site%3Agithub.com+filetype%3Ad
I clicked through quite a few. Every function that's a valid copy constructor by the definition here does indeed perform a valid copy construction with no side-effects, as predicted. Existing functions interpreted as copy constructors under this DIP would continue to work as intended. There's a ridiculously low probability that any such wild function that would be broken by a no-attribute version of this DIP exists.
Jul 17 2018
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 7/12/18 11:01 PM, Manu wrote:
 What existing code are you changing the semantics of?
 It's still not clear to me how accepting `this(ref T)` as a magic
 signature that is a copy constructor can break existing code?
 Is it the unlikely^^2 case that the function exists somewhere and
 doesn't perform copy construction?
    1. the function is highly unlikely to exist because postblit; it's a
 meaningless function to write. are there any known instances of that
 signature in the wild?
    2. if the function does exist, it's highly unlikely that it doesn't
 perform a valid copy construction; what else could it possibly do?
    3. remaining cases are broken by this DIP, but they are probably
 crazy and deserve to be deprecated!
 
 Is there any reasonable existing use of the signature that would be
 legitimately broken by being invoked implicitly?
 I feel like there's something that I'm missing... but if there's not,
 then just change the semantic.
 
 I reason; copy construction is something so fundamental. It will be
 written by basically every programmer with relative high frequently,
 and adding awkward syntax or weird language baggage to the concept
 feels like a very poor choice.
 By contrast, if there's 1 user out there who used the copy-constructor
 signature to do some weird thing other than copy construction, and
 their code is broken by this change, his use case does not balance the
 imposition applied to every implementation of copy constructor forever
 from this time forward.
 This is so much more important than that, it's extremely fundamental
 language stuff, and needs to be as friction-less as possible, and it
 should certainly not reek of legacy drama.
Noted. So in summary you would be okay with changing semantics of existing code, under the intuition that the change is unlikely to be destructive anyway.
Jul 13 2018
parent Manu <turkeyman gmail.com> writes:
On Fri, 13 Jul 2018 at 07:40, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 7/12/18 11:01 PM, Manu wrote:
 What existing code are you changing the semantics of?
 It's still not clear to me how accepting `this(ref T)` as a magic
 signature that is a copy constructor can break existing code?
 Is it the unlikely^^2 case that the function exists somewhere and
 doesn't perform copy construction?
    1. the function is highly unlikely to exist because postblit; it's a
 meaningless function to write. are there any known instances of that
 signature in the wild?
    2. if the function does exist, it's highly unlikely that it doesn't
 perform a valid copy construction; what else could it possibly do?
    3. remaining cases are broken by this DIP, but they are probably
 crazy and deserve to be deprecated!

 Is there any reasonable existing use of the signature that would be
 legitimately broken by being invoked implicitly?
 I feel like there's something that I'm missing... but if there's not,
 then just change the semantic.

 I reason; copy construction is something so fundamental. It will be
 written by basically every programmer with relative high frequently,
 and adding awkward syntax or weird language baggage to the concept
 feels like a very poor choice.
 By contrast, if there's 1 user out there who used the copy-constructor
 signature to do some weird thing other than copy construction, and
 their code is broken by this change, his use case does not balance the
 imposition applied to every implementation of copy constructor forever
 from this time forward.
 This is so much more important than that, it's extremely fundamental
 language stuff, and needs to be as friction-less as possible, and it
 should certainly not reek of legacy drama.
Noted. So in summary you would be okay with changing semantics of existing code, under the intuition that the change is unlikely to be destructive anyway.
Yes, I think this is too important and fundamental to lug historical baggage along with it for the rest of time. That said, I'm firmly in favour of implicit, but the terms of introduction here are not satisfying. If we're going to add yet another attribute, I want to know it's a really good attribute. Adding a whole new attribute just as a marker in this case, and no clear sign that it may or may not be developed into an obvious extension of the concept (and what that looks like) is not satisfactory grounds to introduce a new attribute. I don't understand your objection to this point. I feel like you of all people should be arguing this case. If the DIP specifies introduction of an attribute, then I can't see how there's not a dependency on specification of the attribute. (That doesn't necessarily mean it must be implemented all at once, but I feel like the spec/intent should be presented up-front)
Jul 13 2018
prev sibling parent Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 07/11/2018 11:11 AM, Atila Neves wrote:
 On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right there...
 so should we expect that an *explicit* call to the copy constructor
 is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
How is this different from other types of constructors or destructors?
The main difference is that the compiler may insert calls to it implicitly.
 I also very much dislike the syntax - it makes no sense to me at all. I
 commented on the PR itself asking why it differs so much from C++ -
 specifically, what's bad about the C++ way of doing things there that we
 want to avoid?
C++ is at the other end of the spectrum - constructors are too implicit, so the "explicit" keyword has been introduced with the advice to use it in the vast majority of cases. If C++ could do it again, it would make everything explicit and add an "implicit" keyword.
Ohhh yeah, this. I finally understand your reasoning here! Okay, that is a meaningful use for implicit, and I could get behind its introduction if it were extended to apply broadly to any constructor. If it's only used in this isolated case, and specifically disallowed in that useful broader case, it feels pointless, and probably a cause of frustration for people that expect that it should work broadly. The DIP mentions that it may be deployed broadly, but I'd like to see that resolved up-front. I could only decide to accept it in this case depending on that secondary decision.
Jul 12 2018
prev sibling next sibling parent reply vit <vit vit.vit> writes:
On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right 
 there... so should we expect that an *explicit* call to the 
 copy constructor is not allowed? Or maybe it is allowed and 
 ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
Can be explicit constructor overloaded with implicit constructor when both have same signature?
Jul 11 2018
next sibling parent Manu <turkeyman gmail.com> writes:
On Wed, 11 Jul 2018 at 09:20, vit via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right
 there... so should we expect that an *explicit* call to the
 copy constructor is not allowed? Or maybe it is allowed and
 ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
Can be explicit constructor overloaded with implicit constructor when both have same signature?
If they've got the same signature, they should do the same thing... what's the overload for?
Jul 11 2018
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/11/2018 12:19 PM, vit wrote:
 On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
 But there's a super explicit ` implicit` thing written right there... 
 so should we expect that an *explicit* call to the copy constructor 
 is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
Can be explicit constructor overloaded with implicit constructor when both have same signature?
Thanks for this. Yes we need to add a mention.
Jul 12 2018
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Wed, 11 Jul 2018 at 00:45, RazvanN via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 But there's a super explicit ` implicit` thing written right
 there... so should we expect that an *explicit* call to the
 copy constructor is not allowed? Or maybe it is allowed and
 ` implicit` is a lie?
The implicit is there to point out that you cannot call that method explicitly; it gets called for you implicitly when you construct an object as a copy of another object.
That's my point; so this is a compile error then: S b = S(a); // <- explicit construction of copy? ie, explicit call to stated ` implicit` function
Jul 11 2018
parent RazvanN <razvan.nitu1305 gmail.com> writes:
 That's my point; so this is a compile error then:
 S b = S(a); // <- explicit construction of copy? ie, explicit 
 call to
 stated ` implicit` function
Consider this code: import std.stdio : writeln; struct S { this(this) { writeln("postblit"); } int a; this(int a) { this.a = a; } this(ref S another) { writeln("calling this"); } } void main() { S a; S b = S(a); } In this situation, the constructor is called; if `this(ref S another)` is commented the code will result in a compilation error "constructor S.this(int) is not callable using argument types (S)", so the postblit is NOT called. In my opinion this is the desired behavior and should be implemented by the copy constructor also. If you are doing `S b = S(a)` then you are explicitly trying to call a constructor; if it doesn't exist, then it's an error; if you wanted to call the copy constructor then you would have done `S b = a;`. Using S(a) states the intention of explicitly calling a constructor while the copy constructor can only be called implicitly.
Jul 12 2018
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/10/2018 06:50 PM, Manu wrote:
 On Tue, 10 Jul 2018 at 15:23, Jonathan M Davis via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
 2. It looks like copy constructors are used to perform assignments
 (and not constructions)... but, there is also opAssign. What gives?
      Eg:
        S b = a; // <- copy construction? looks like an assignment.
      And not:
        S b = S(a); // <- actually looks like a construction, but this
 syntax seems to not be intended (and rightly so, it's pretty terrible)
S b = a; has never been assignment in either C++ or D. It's initialization / construction, which means that it calls a constructor - be that a postblit constructor or a copy constructor. Assignment only occurs when you're giving an existing object a new value.
I know this, but it's not syntactically obvious, it just depends on the fact that you already know that fact... I feel a DIP about copy construction needs to have some text explaining that, and where the edges are.
The DIP is not a tutorial on existing related parts of the language. Copy initialization has been distinct from assignment for a long time in both C++ and D languages.
 Is an initialisation assignment can use a copy constructor, why can't
 a normal assignment implicitly use a copy constructor? (implicit
 destruct then copy-construct)
Because assignment and construction were, and are, distinct operation. There is no need for the DIP to explain.
 And why would

 S b = S(a);

 not be intended? Sure, it's kind of pointless if a is an S, but if you have
 a copy constructor, it makes perfect sense that S(a) would work and would be
 pretty bizarre if it didn't, since it's explicitly calling the copy
 constructor.
But there's a super explicit ` implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The " implicit" attribute does not preclude explicit calls. Razvan: you may want to mention that.
 It even works right now if you give S a constructor that takes
 an S. It just isn't actually treated as a proper copy constructor at the
 moment, since that's currently the postblit constructor's job.
Current language doesn't have ` implicit` written anywhere...
Misunderstanding that I assume has been cleared by now. Andrei
Jul 12 2018
parent Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 06:45, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 07/10/2018 06:50 PM, Manu wrote:
 On Tue, 10 Jul 2018 at 15:23, Jonathan M Davis via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
 2. It looks like copy constructors are used to perform assignments
 (and not constructions)... but, there is also opAssign. What gives?
      Eg:
        S b = a; // <- copy construction? looks like an assignment.
      And not:
        S b = S(a); // <- actually looks like a construction, but this
 syntax seems to not be intended (and rightly so, it's pretty terrible)
S b = a; has never been assignment in either C++ or D. It's initialization / construction, which means that it calls a constructor - be that a postblit constructor or a copy constructor. Assignment only occurs when you're giving an existing object a new value.
I know this, but it's not syntactically obvious, it just depends on the fact that you already know that fact... I feel a DIP about copy construction needs to have some text explaining that, and where the edges are.
The DIP is not a tutorial on existing related parts of the language. Copy initialization has been distinct from assignment for a long time in both C++ and D languages.
Okay. Well, I guess that I just wanted some clarity on exactly what 'initialisation' looks like. T b = a; // clearly initialisation, sure T c = T(a); // c is initialised to a copy of an rvalue which was initialised as a copy of a. Is there *two* calls to the copy constructor here? In this way, is an explicit call to the copy constructor is allowed? You said it is, but the word " implicit" makes it look like explicit calls should be an arbitrary error; change the word at least. C++ is a disaster zone these days with `T t = x;` `T t = T(x);` `T t(x);` `T t{x};`... I just wanna make sure we don't end up with initialisation 'cases'.
 Is an initialisation assignment can use a copy constructor, why can't
 a normal assignment implicitly use a copy constructor? (implicit
 destruct then copy-construct)
Because assignment and construction were, and are, distinct operation. There is no need for the DIP to explain.
Right, but as I've alluded to before, there's a loose relationship here. C++ prescribes the 'rule of 3' (or 5). If we introduce copy constructors, are we introducing those concepts? I think introduction of those concepts may pull questions about assignment into the definition space.
 And why would

 S b = S(a);

 not be intended? Sure, it's kind of pointless if a is an S, but if you have
 a copy constructor, it makes perfect sense that S(a) would work and would be
 pretty bizarre if it didn't, since it's explicitly calling the copy
 constructor.
But there's a super explicit ` implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and ` implicit` is a lie?
The " implicit" attribute does not preclude explicit calls. Razvan: you may want to mention that.
Okay. In that case, I really don't like the name.
Jul 12 2018
prev sibling next sibling parent reply Nick Treleaven <nick geany.org> writes:
On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
 [1] https://github.com/dlang/DIPs/pull/129
Thanks for making the DIP. I can't get this code to compile (my struct has an `int i` field): static foreach (i, ref field; src.tupleof) this.tupleof[i] = field; Error: constant value src.i cannot be ref https://run.dlang.io/is/qeugC8 Removing `static` works. Otherwise I tried changing `ref` to `alias`: Error: variable src cannot be read at compile time But this shorter code seems to work fine: this.tupleof = src.tupleof;
Jul 11 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/11/2018 05:55 AM, Nick Treleaven wrote:
 On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
 [1] https://github.com/dlang/DIPs/pull/129
Thanks for making the DIP. I can't get this code to compile (my struct has an `int i` field): static foreach (i, ref field; src.tupleof)     this.tupleof[i] = field; Error: constant value src.i cannot be ref https://run.dlang.io/is/qeugC8 Removing `static` works. Otherwise I tried changing `ref` to `alias`: Error: variable src cannot be read at compile time But this shorter code seems to work fine: this.tupleof = src.tupleof;
Odd. Timon, what would be the reason for that error? Razvan, can you please look into removing "static" for now. Thanks!
Jul 12 2018
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12.07.2018 15:29, Andrei Alexandrescu wrote:
 On 07/11/2018 05:55 AM, Nick Treleaven wrote:
 ...

 Removing `static` works. Otherwise I tried changing `ref` to `alias`:

 Error: variable src cannot be read at compile time

 But this shorter code seems to work fine:

 this.tupleof = src.tupleof;
Odd. Timon, what would be the reason for that error? Razvan, can you please look into removing "static" for now. Thanks!
The reason for this specific error is that `src.i` is neither a symbol nor a constant value. tupleof is a case of built-in compiler magic, because it can produce an expression tuple that contains run-time values that are not symbols. The following (manually unrolled) code also does not work: alias field0 = s.tupleof[0]; t.tupleof[0] = field0; alias field1 = s.tupleof[1]; t.tupleof[1] = field1; alias field2 = s.tupleof[2]; t.tupleof[2] = field2; Error: alias `a` cannot alias an expression `tuple(s.a, s.b, s.c)[0]` Error: alias `b` cannot alias an expression `tuple(s.a, s.b, s.c)[1]` Error: alias `c` cannot alias an expression `tuple(s.a, s.b, s.c)[2]` It could be argued that the `static foreach` implementation should produce the same error message. (The fact that the AliasDecl constructor takes a Dsymbol instead of an Expression has led to multiple reimplementations of parts of the aliasing logic in different parts of the DMD code, `static foreach` is using the same implementation also used by unrolled foreach, and it requires that all loop variables are either symbols or constant values, while unrolled foreach can fall back to introducing runtime variables for this special case.) One way to fix is to lift all the unnecessary limitations that are introduced by the fact that the AliasDecl constructor takes a Dsymbol. I.e. that "you can only alias symbols". Alternatively, it would be possible to redefine `static foreach` statements such that they work for any aggregate with statically known length and element types, and to allow run-time loop variables to be generated when iterating over run-time values.
Jul 12 2018
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12.07.2018 17:22, Timon Gehr wrote:
 
 alias field0 = s.tupleof[0];
 t.tupleof[0] = field0;
 alias field1 = s.tupleof[1];
 t.tupleof[1] = field1;
 alias field2 = s.tupleof[2];
 t.tupleof[2] = field2;
 
 Error: alias `a` cannot alias an expression `tuple(s.a, s.b, s.c)[0]`
 Error: alias `b` cannot alias an expression `tuple(s.a, s.b, s.c)[1]`
 Error: alias `c` cannot alias an expression `tuple(s.a, s.b, s.c)[2]`
The error messages are actually: Error: alias `field0` cannot alias an expression `tuple(s.a, s.b, s.c)[0]` Error: alias `field1` cannot alias an expression `tuple(s.a, s.b, s.c)[1]` Error: alias `field2` cannot alias an expression `tuple(s.a, s.b, s.c)[2]`
Jul 12 2018
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2018 11:22 AM, Timon Gehr wrote:
 On 12.07.2018 15:29, Andrei Alexandrescu wrote:
 On 07/11/2018 05:55 AM, Nick Treleaven wrote:
 ...

 Removing `static` works. Otherwise I tried changing `ref` to `alias`:

 Error: variable src cannot be read at compile time

 But this shorter code seems to work fine:

 this.tupleof = src.tupleof;
Odd. Timon, what would be the reason for that error? Razvan, can you please look into removing "static" for now. Thanks!
The reason for this specific error is that `src.i` is neither a symbol nor a constant value. tupleof is a case of built-in compiler magic, because it can produce an expression tuple that contains run-time values that are not symbols. The following (manually unrolled) code also does not work: alias field0 = s.tupleof[0]; t.tupleof[0] = field0; alias field1 = s.tupleof[1]; t.tupleof[1] = field1; alias field2 = s.tupleof[2]; t.tupleof[2] = field2; Error: alias `a` cannot alias an expression `tuple(s.a, s.b, s.c)[0]` Error: alias `b` cannot alias an expression `tuple(s.a, s.b, s.c)[1]` Error: alias `c` cannot alias an expression `tuple(s.a, s.b, s.c)[2]` It could be argued that the `static foreach` implementation should produce the same error message. (The fact that the AliasDecl constructor takes a Dsymbol instead of an Expression has led to multiple reimplementations of parts of the aliasing logic in different parts of the DMD code, `static foreach` is using the same implementation also used by unrolled foreach, and it requires that all loop variables are either symbols or constant values, while unrolled foreach can fall back to introducing runtime variables for this special case.) One way to fix is to lift all the unnecessary limitations that are introduced by the fact that the AliasDecl constructor takes a Dsymbol. I.e. that "you can only alias symbols". Alternatively, it would be possible to redefine `static foreach` statements such that they work for any aggregate with statically known length and element types, and to allow run-time loop variables to be generated when iterating over run-time values.
Thanks!
Jul 12 2018
prev sibling next sibling parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
 I managed to put together a first draft of the DIP for adding 
 the copy constructor to the language [1]. If anyone is 
 interested, please take a look. Suggestions and comments about 
 technical aspects and wording are all welcome.
When designing D libraries than lean towards DSL style, I've frequently felt impaired by the lack of implicit conversions in D. In my experience, it's not that all types need to be implicitly convertible to other types. Just being able to mark a few types as implicitly convertible to some other specific types would go a long way to alleviate the limitations I felt. It would also solve problems like an arbitrary limit on the depth of implicit conversions. I had imagined that maybe one day an implicit keyword could be introduced to mark such permissible implicit conversions. Seeing an implicit "keyword" being introduced here with different semantics than I envisioned makes me even less hopeful that some day such implicit conversions annotations could be introduced. So... maybe consider choosing some other syntactic notation? Besides, the fact that the compiler can implicitly introduce calls to the copy ctor doesn't strike me as something particularly central to the concept, so it seems like an odd choice for something to distinguish a copy ctor.
Jul 12 2018
parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Thursday, 12 July 2018 at 14:56:33 UTC, Luís Marques wrote:
 When designing D libraries than lean towards DSL style, I've 
 frequently felt impaired by the lack of implicit conversions in 
 D. In my experience, it's not that all types need to be 
 implicitly convertible to other types. Just being able to mark 
 a few types as implicitly convertible to some other specific 
 types would go a long way to alleviate the limitations I felt.  
 It would also solve problems like an arbitrary limit on the 
 depth of implicit conversions.

 I had imagined that maybe one day an implicit keyword could be 
 introduced to mark such permissible implicit conversions. 
 Seeing an implicit "keyword" being introduced here with 
 different semantics than I envisioned makes me even less 
 hopeful that some day such implicit conversions annotations 
 could be introduced. So... maybe consider choosing some other 
 syntactic notation? Besides, the fact that the compiler can 
 implicitly introduce calls to the copy ctor doesn't strike me 
 as something particularly central to the concept, so it seems 
 like an odd choice for something to distinguish a copy ctor.
More details. The DIP says: "The structName type needs to be identical to typeof(this); an error is issued otherwise. This requirement may be relaxed in the future in order to accomodate copying from objects of a different type" (BTW, typo in "accomodate") That would mean that if such a relaxation were introduced, then suddenly *all* copy ctors would imply implicit conversion between the respective types. Given D's stance on implicit conversions, I suspect that's not going to pass mustard. So I would prefer the any "implicit" keyword-like annotation to be reserved for explicitly approved implicit conversions.
Jul 12 2018
next sibling parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Thursday, 12 July 2018 at 15:14:19 UTC, Luís Marques wrote:
 More details. The DIP says:

 "The structName type needs to be identical to typeof(this); an 
 error is issued otherwise. This requirement may be relaxed in 
 the future in order to accomodate copying from objects of a 
 different type"
 (BTW, typo in "accomodate")

 That would mean that if such a relaxation were introduced, then 
 suddenly *all* copy ctors would imply implicit conversion 
 between the respective types. Given D's stance on implicit 
 conversions, I suspect that's not going to pass mustard. So I 
 would prefer the any "implicit" keyword-like annotation to be 
 reserved for explicitly approved implicit conversions.
BTW: Multiple alias this is still planned for inclusion in D, right? If so, what would be the (pratical?) difference between having copy ctors with such a relaxed type requirement and just defining an equivalent alias this method? In case the answer is that there's no significant difference, why not drop multiple alias this, then?
Jul 12 2018
next sibling parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Thursday, 12 July 2018 at 15:25:10 UTC, Luís Marques wrote:
 On Thursday, 12 July 2018 at 15:14:19 UTC, Luís Marques wrote:
 BTW: Multiple alias this is still planned for inclusion in D, 
 right? If so, what would be the (pratical?) difference between 
 having copy ctors with such a relaxed type requirement and just 
 defining an equivalent alias this method? In case the answer is 
 that there's no significant difference, why not drop multiple 
 alias this, then?
Sorry for the stream-of-conscience type posts. But, to clarify further: if alias this provides access to the members of the converted type (besides type conversion), couldn't that feature be folded into the same mechanism of the copy ctor (or vice-versa), to avoid mostly redundant features in the language, with subtle interactions?
Jul 12 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2018 11:29 AM, Luís Marques wrote:
 On Thursday, 12 July 2018 at 15:25:10 UTC, Luís Marques wrote:
 On Thursday, 12 July 2018 at 15:14:19 UTC, Luís Marques wrote:
 BTW: Multiple alias this is still planned for inclusion in D, right? 
 If so, what would be the (pratical?) difference between having copy 
 ctors with such a relaxed type requirement and just defining an 
 equivalent alias this method? In case the answer is that there's no 
 significant difference, why not drop multiple alias this, then?
Sorry for the stream-of-conscience type posts. But, to clarify further: if alias this provides access to the members of the converted type (besides type conversion), couldn't that feature be folded into the same mechanism of the copy ctor (or vice-versa), to avoid mostly redundant features in the language, with subtle interactions?
The DIP mentions the interaction of implicit with alias this.
Jul 12 2018
parent =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Thursday, 12 July 2018 at 15:34:25 UTC, Andrei Alexandrescu 
wrote:
 The DIP mentions the interaction of  implicit with alias this.
Not the interaction I was asking about, although admittedly it was speculative.
Jul 12 2018
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2018 11:25 AM, Luís Marques wrote:
 On Thursday, 12 July 2018 at 15:14:19 UTC, Luís Marques wrote:
 More details. The DIP says:

 "The structName type needs to be identical to typeof(this); an error 
 is issued otherwise. This requirement may be relaxed in the future in 
 order to accomodate copying from objects of a different type"
 (BTW, typo in "accomodate")

 That would mean that if such a relaxation were introduced, then 
 suddenly *all* copy ctors would imply implicit conversion between the 
 respective types. Given D's stance on implicit conversions, I suspect 
 that's not going to pass mustard. So I would prefer the any "implicit" 
 keyword-like annotation to be reserved for explicitly approved 
 implicit conversions.
BTW: Multiple alias this is still planned for inclusion in D, right? If so, what would be the (pratical?) difference between having copy ctors with such a relaxed type requirement and just defining an equivalent alias this method? In case the answer is that there's no significant difference, why not drop multiple alias this, then?
Again: not the charter of this DIP, so you should ask yourself, not us, this question.
Jul 12 2018
parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Thursday, 12 July 2018 at 15:33:03 UTC, Andrei Alexandrescu 
wrote:
 Again: not the charter of this DIP, so you should ask yourself, 
 not us, this question.
Look, I understand it can be frustrating to have a concrete design proposal derailed by a myriad of speculative questions. But if we suspect that design decision of a DIP might interact poorly with other plausible future D features, should we not at least express our concerns and hopes? By the time the other DIPs come out it might be too late to address the concerns. In any case, I hope my comments were not too out of bounds of the discussion. If so, I'm sorry.
Jul 12 2018
next sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 12 July 2018 at 15:42:29 UTC, Luís Marques wrote:
 On Thursday, 12 July 2018 at 15:33:03 UTC, Andrei Alexandrescu 
 wrote:
 Again: not the charter of this DIP, so you should ask 
 yourself, not us, this question.
Look, I understand it can be frustrating to have a concrete design proposal derailed by a myriad of speculative questions. But if we suspect that design decision of a DIP might interact poorly with other plausible future D features, should we not at least express our concerns and hopes? By the time the other DIPs come out it might be too late to address the concerns. In any case, I hope my comments were not too out of bounds of the discussion. If so, I'm sorry.
I like the idea of implicit conversions (until I've been convinced otherwise at least), but I don't necessarily think this DIP will interact poorly with it. They could be implemented with a new opImplicitCast. Less elegantly, you could have special behavior when implicit is used with opCast.
Jul 12 2018
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/18 11:42 AM, Luís Marques wrote:
 On Thursday, 12 July 2018 at 15:33:03 UTC, Andrei Alexandrescu wrote:
 Again: not the charter of this DIP, so you should ask yourself, not 
 us, this question.
Look, I understand it can be frustrating to have a concrete design proposal derailed by a myriad of speculative questions. But if we suspect that design decision of a DIP might interact poorly with other plausible future D features, should we not at least express our concerns and hopes? By the time the other DIPs come out it might be too late to address the concerns. In any case, I hope my comments were not too out of bounds of the discussion. If so, I'm sorry.
Definitely good topics to discuss. This is a collaborative process, not a confrontational one. If this DIP precludes good future decisions, that's definitely a meaningful discussion.
Jul 12 2018
prev sibling parent Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 08:30, Luís Marques via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Thursday, 12 July 2018 at 15:14:19 UTC, Luís Marques wrote:
 More details. The DIP says:

 "The structName type needs to be identical to typeof(this); an
 error is issued otherwise. This requirement may be relaxed in
 the future in order to accomodate copying from objects of a
 different type"
 (BTW, typo in "accomodate")

 That would mean that if such a relaxation were introduced, then
 suddenly *all* copy ctors would imply implicit conversion
 between the respective types. Given D's stance on implicit
 conversions, I suspect that's not going to pass mustard. So I
 would prefer the any "implicit" keyword-like annotation to be
 reserved for explicitly approved implicit conversions.
BTW: Multiple alias this is still planned for inclusion in D, right? If so, what would be the (pratical?) difference between having copy ctors with such a relaxed type requirement and just defining an equivalent alias this method? In case the answer is that there's no significant difference, why not drop multiple alias this, then?
implicit constructors state what types an object may *accept*. alias this specifies what types an object may *provide*. They're both about implicit conversion, but specified at either the providing or receiving end. I think they both have reason to exist; they're complementary. It depends if you're authoring an API, or writing a tool to interact with an existing API which is appropriate to use.
Jul 12 2018
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2018 11:14 AM, Luís Marques wrote:
 On Thursday, 12 July 2018 at 14:56:33 UTC, Luís Marques wrote:
 When designing D libraries than lean towards DSL style, I've 
 frequently felt impaired by the lack of implicit conversions in D. In 
 my experience, it's not that all types need to be implicitly 
 convertible to other types. Just being able to mark a few types as 
 implicitly convertible to some other specific types would go a long 
 way to alleviate the limitations I felt. It would also solve problems 
 like an arbitrary limit on the depth of implicit conversions.

 I had imagined that maybe one day an implicit keyword could be 
 introduced to mark such permissible implicit conversions. Seeing an 
 implicit "keyword" being introduced here with different semantics than 
 I envisioned makes me even less hopeful that some day such implicit 
 conversions annotations could be introduced. So... maybe consider 
 choosing some other syntactic notation? Besides, the fact that the 
 compiler can implicitly introduce calls to the copy ctor doesn't 
 strike me as something particularly central to the concept, so it 
 seems like an odd choice for something to distinguish a copy ctor.
More details. The DIP says: "The structName type needs to be identical to typeof(this); an error is issued otherwise. This requirement may be relaxed in the future in order to accomodate copying from objects of a different type" (BTW, typo in "accomodate") That would mean that if such a relaxation were introduced, then suddenly *all* copy ctors would imply implicit conversion between the respective types.
No, only constructors annotated with implicit would be implicit. But that's only a possible future direction not part of this DIP. Also there are many complications related to allowing implicit conversions across distinct types, and this DIP should not get embroiled in those. That would be a different pursuit that I encourage you to consider.
Jul 12 2018
parent reply Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 08:36, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 07/12/2018 11:14 AM, Luís Marques wrote:
 On Thursday, 12 July 2018 at 14:56:33 UTC, Luís Marques wrote:
 When designing D libraries than lean towards DSL style, I've
 frequently felt impaired by the lack of implicit conversions in D. In
 my experience, it's not that all types need to be implicitly
 convertible to other types. Just being able to mark a few types as
 implicitly convertible to some other specific types would go a long
 way to alleviate the limitations I felt. It would also solve problems
 like an arbitrary limit on the depth of implicit conversions.

 I had imagined that maybe one day an implicit keyword could be
 introduced to mark such permissible implicit conversions. Seeing an
 implicit "keyword" being introduced here with different semantics than
 I envisioned makes me even less hopeful that some day such implicit
 conversions annotations could be introduced. So... maybe consider
 choosing some other syntactic notation? Besides, the fact that the
 compiler can implicitly introduce calls to the copy ctor doesn't
 strike me as something particularly central to the concept, so it
 seems like an odd choice for something to distinguish a copy ctor.
More details. The DIP says: "The structName type needs to be identical to typeof(this); an error is issued otherwise. This requirement may be relaxed in the future in order to accomodate copying from objects of a different type" (BTW, typo in "accomodate") That would mean that if such a relaxation were introduced, then suddenly *all* copy ctors would imply implicit conversion between the respective types.
No, only constructors annotated with implicit would be implicit. But that's only a possible future direction not part of this DIP. Also there are many complications related to allowing implicit conversions across distinct types, and this DIP should not get embroiled in those. That would be a different pursuit that I encourage you to consider.
I feel like this DIP depends on an implicit DIP, and that one needs to come first...
Jul 12 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/18 7:15 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 08:36, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 07/12/2018 11:14 AM, Luís Marques wrote:
 On Thursday, 12 July 2018 at 14:56:33 UTC, Luís Marques wrote:
 When designing D libraries than lean towards DSL style, I've
 frequently felt impaired by the lack of implicit conversions in D. In
 my experience, it's not that all types need to be implicitly
 convertible to other types. Just being able to mark a few types as
 implicitly convertible to some other specific types would go a long
 way to alleviate the limitations I felt. It would also solve problems
 like an arbitrary limit on the depth of implicit conversions.

 I had imagined that maybe one day an implicit keyword could be
 introduced to mark such permissible implicit conversions. Seeing an
 implicit "keyword" being introduced here with different semantics than
 I envisioned makes me even less hopeful that some day such implicit
 conversions annotations could be introduced. So... maybe consider
 choosing some other syntactic notation? Besides, the fact that the
 compiler can implicitly introduce calls to the copy ctor doesn't
 strike me as something particularly central to the concept, so it
 seems like an odd choice for something to distinguish a copy ctor.
More details. The DIP says: "The structName type needs to be identical to typeof(this); an error is issued otherwise. This requirement may be relaxed in the future in order to accomodate copying from objects of a different type" (BTW, typo in "accomodate") That would mean that if such a relaxation were introduced, then suddenly *all* copy ctors would imply implicit conversion between the respective types.
No, only constructors annotated with implicit would be implicit. But that's only a possible future direction not part of this DIP. Also there are many complications related to allowing implicit conversions across distinct types, and this DIP should not get embroiled in those. That would be a different pursuit that I encourage you to consider.
I feel like this DIP depends on an implicit DIP, and that one needs to come first...
Negative.
Jul 12 2018
parent reply Manu <turkeyman gmail.com> writes:
On Thu., 12 Jul. 2018, 7:10 pm Andrei Alexandrescu via Digitalmars-d, <
digitalmars-d puremagic.com> wrote:

 On 7/12/18 7:15 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 08:36, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 07/12/2018 11:14 AM, Lu=C3=ADs Marques wrote:
 On Thursday, 12 July 2018 at 14:56:33 UTC, Lu=C3=ADs Marques wrote:
 When designing D libraries than lean towards DSL style, I've
 frequently felt impaired by the lack of implicit conversions in D. I=
n
 my experience, it's not that all types need to be implicitly
 convertible to other types. Just being able to mark a few types as
 implicitly convertible to some other specific types would go a long
 way to alleviate the limitations I felt. It would also solve problem=
s
 like an arbitrary limit on the depth of implicit conversions.

 I had imagined that maybe one day an implicit keyword could be
 introduced to mark such permissible implicit conversions. Seeing an
 implicit "keyword" being introduced here with different semantics th=
an
 I envisioned makes me even less hopeful that some day such implicit
 conversions annotations could be introduced. So... maybe consider
 choosing some other syntactic notation? Besides, the fact that the
 compiler can implicitly introduce calls to the copy ctor doesn't
 strike me as something particularly central to the concept, so it
 seems like an odd choice for something to distinguish a copy ctor.
More details. The DIP says: "The structName type needs to be identical to typeof(this); an error =
is
 issued otherwise. This requirement may be relaxed in the future in
order
 to accomodate copying from objects of a different type"
 (BTW, typo in "accomodate")

 That would mean that if such a relaxation were introduced, then
suddenly
 *all* copy ctors would imply implicit conversion between the respecti=
ve
 types.
No, only constructors annotated with implicit would be implicit. But that's only a possible future direction not part of this DIP. Also there are many complications related to allowing implicit conversions across distinct types, and this DIP should not get embroil=
ed
 in those. That would be a different pursuit that I encourage you to
 consider.
I feel like this DIP depends on an implicit DIP, and that one needs to come first...
Negative.
Double-negative.. why would we support introduction of this implicit attribute if it's not proposed how it will work in general? Introducing more attributes is a big deal. For the record, now that I 'get it', I'm super jazzed about having implicit in the language. I've wanted it since day-one! But I don't want to be swindled into accepting its existence prior to being comfortable that the design/intent/implementation is right. We can't get it out if the theoretical future DIP that makes it broadly useful is not agreeable. The potential introduction of implicit makes me about 100x more interested (and critical) of this DIP. Now that it's on the table, I *really* care that this goes right. Seriously, if I was making this proposal to you, and you were in my position... there is no way in hell that you'd allow any of us to slip something so substantial by like that with the wave of a hand. This DIP depends on implicit. How can you argue otherwise?
Jul 12 2018
parent reply Meta <jared771 gmail.com> writes:
On Friday, 13 July 2018 at 02:32:59 UTC, Manu wrote:
 Seriously, if I was making this proposal to you, and you were 
 in my
 position... there is no way in hell that you'd allow any of us 
 to slip
 something so substantial by like that with the wave of a hand.
 This DIP depends on  implicit. How can you argue otherwise?
Nothing is being slipped by as far as I'm concerned. implicit is solely introduced in the DIP as a marker for the copy constructor, and it doesn't seem like it's intended for anything further than avoiding breaking code. It feels to me like you're making a mountain out of an ant hill. Still, regardless of what the intention was, implicit was a poor choice of words for exactly this reason. The DIP itself seems solid. Makes me a little nervous to be introducing copy constructors, but if it's really that untenable to typecheck qualified postblits, then I'm all for it. One step closer to eliminating Qualified Hell when wrapping structs in other structs.
Jul 12 2018
parent reply Manu <turkeyman gmail.com> writes:
On Thu, 12 Jul 2018 at 20:15, Meta via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Friday, 13 July 2018 at 02:32:59 UTC, Manu wrote:
 Seriously, if I was making this proposal to you, and you were
 in my
 position... there is no way in hell that you'd allow any of us
 to slip
 something so substantial by like that with the wave of a hand.
 This DIP depends on  implicit. How can you argue otherwise?
Nothing is being slipped by as far as I'm concerned. implicit is solely introduced in the DIP as a marker for the copy constructor, and it doesn't seem like it's intended for anything further than avoiding breaking code. It feels to me like you're making a mountain out of an ant hill.
That's the whole point though. We're debating whether " implicit" is a good idea. And it's the only detail of the DIP that feels noteworthy or contentious to me. The rest is pretty much common-sense, and long overdue. I can see myself getting behind 2 possibilities, no implicit, or implicit done right. I don't see myself getting behind introduction of implicit on such terms that it's nothing but "a marker for the copy constructor". So this 'mountain' is critical to understanding whether I can support this DIP as proposed or not.
 Still, regardless of what the intention was,  implicit was a poor
 choice of words for exactly this reason.
I disagree; it's the perfect choice assuming an " implicit done right" future. And if that's the case, I'll get behind that with all my insignificant weight, but we need to know how it's defined up front. If we're not assuming that, then the conversation goes completely differently, and I would want to resist any such attribute or marker for the time being until we can explore that other future. We can't make a decision about it unless we know where it's destined. Also, this 'ant hill' is _copy construction_, there are few mechanics we could be talking about so fundamentally important and significant to the future of the language. Copy construction is HUGE! This is our one chance to correct some major mistakes from the past, and I'm glad it's being worked on.
Jul 12 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 7/12/18 11:45 PM, Manu wrote:
 On Thu, 12 Jul 2018 at 20:15, Meta via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 
 On Friday, 13 July 2018 at 02:32:59 UTC, Manu wrote:
 Seriously, if I was making this proposal to you, and you were in
 my position... there is no way in hell that you'd allow any of
 us to slip something so substantial by like that with the wave of
 a hand. This DIP depends on  implicit. How can you argue
 otherwise?
Nothing is being slipped by as far as I'm concerned. implicit is solely introduced in the DIP as a marker for the copy constructor, and it doesn't seem like it's intended for anything further than avoiding breaking code. It feels to me like you're making a mountain out of an ant hill.
That's the whole point though. We're debating whether " implicit" is a good idea. And it's the only detail of the DIP that feels noteworthy or contentious to me. The rest is pretty much common-sense, and long overdue. I can see myself getting behind 2 possibilities, no implicit, or implicit done right.
A couple of simple ideas are making the process productive. One is to rely on facts instead of feelings. "It's weird" or "I don't like it" are less helpful than "semantics of this or that case are not covered". Another is precision. Stating vague goals and standards ("I want implicit done well") and systematically asking others to actually put in the work is less desirable than providing concrete, motivated, actionable feedback. To the second point: we have a history of defining features too permissively, to then regret not having waited to accumulate experience. Starting with a restricted version then building on experience with it seems to be a much better strategy. From that perspective, introducing implicit only for restricted copy construction seems like a good step that doesn't take others, without precluding them.
 I don't see myself getting behind introduction of  implicit on such 
 terms that it's nothing but "a marker for the copy constructor". So 
 this 'mountain' is critical to understanding whether I can support 
 this DIP as proposed or not.
I'd put it a slightly different way. "Getting behind" and "supporting or not" suggests a position of power and an emphasis on the politics of the process. The natural counter to this would be asking whether your support is necessary, which put us all in a very unproductive position. The right emphasis is not getting your support on a given DIP, but instead us all benefiting of your active contribution to a better DIP. Thanks, Andrei
Jul 13 2018
parent reply Manu <turkeyman gmail.com> writes:
On Fri, 13 Jul 2018 at 07:35, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 7/12/18 11:45 PM, Manu wrote:
 I can see myself getting behind 2 possibilities, no  implicit, or
  implicit done right.
A couple of simple ideas are making the process productive. One is to rely on facts instead of feelings. "It's weird" or "I don't like it" are less helpful than "semantics of this or that case are not covered".
What "I don't like" is using an attribute as a marker, and especially in the unique case of a copy constructor, which is so fundamental to the language. If it has a systemic meaning, as it's sort-of proposed that maybe it might in the future sometime, then it's fine. There's a lot of subjectivity in programming. I don't like that python has significant white-space. I don't like that Javascript isn't a native language. I don't like the idea of introducing an attribute as a marker in a single case, without some expectation that it has a future beyond that.
 Another is precision. Stating vague goals and standards ("I want
  implicit done well") and systematically asking others to actually put
 in the work is less desirable than providing concrete, motivated,
 actionable feedback.
As I originally said, my feedback is concrete: specify implicit, this DIP depends on it. My language like " implicit done right" came later, as a reference to prior comments. As I've said, I actually really want implicit, but I want to be satisfied by it's definition and somewhat convinced that it has a future, and specifically, that it's NOT just a marker to be used in this case. It's not about 'asking others to put in the work', this DIP has a dependency on it, so it can't not be defined. The definition is currently "it's a marker, and maybe we might do something in the future", and that's a poor definition. If I presented a DIP which casually dropped in a new attribute, you would absolutely insist that I specify it.
 To the second point: we have a history of defining features too
 permissively, to then regret not having waited to accumulate experience.
 Starting with a restricted version then building on experience with it
 seems to be a much better strategy. From that perspective, introducing
 implicit only for restricted copy construction seems like a good step
 that doesn't take others, without precluding them.
There's also property... and 'scope' as existed prior DIP1000, and 'in'. I think this thing needs at least a little spec-ing. If it's clear up front that it's not going anywhere (easily shot-down or whatever), then it's not a good choice. If it looks generally promising for the future, and there's no obvious roadblocks for wider deployment, then we're good, and I'll desist on this point. I don't know how we can be confident of that without at least a little exploration.
 I don't see myself getting behind introduction of  implicit on such
 terms that it's nothing but "a marker for the copy constructor". So
 this 'mountain' is critical to understanding whether I can support
 this DIP as proposed or not.
I'd put it a slightly different way. "Getting behind" and "supporting or not" suggests a position of power and an emphasis on the politics of the process. The natural counter to this would be asking whether your support is necessary, which put us all in a very unproductive position.
Presenting a proposal to the community is an implicit request for support. I'm not saying I have any power further than my reading of the proposal and sharing my own judgement of its merit. You can do whatever you do... I'm just saying what I find satisfying, and this proposal is not satisfying without some further substantiation of the proposed new attribute.
 The right emphasis is not getting your support on a given DIP, but
 instead us all benefiting of your active contribution to a better DIP.
I've already contributed other points to this DIP in the way you describe. This one however is very strange, and I'm surprised you can find the hand-wavy introduction of a new attribute without any sense of where it's going to be okay. Or maybe, I'm surprised I'm the only one that finds problem with that. My feeling is inspired by ' property', 'scope', 'in'. We don't need any more events like those.
Jul 13 2018
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 14/07/2018 9:28 AM, Manu wrote:
 I've already contributed other points to this DIP in the way you describe.
 This one however is very strange, and I'm surprised you can find the
 hand-wavy introduction of a new attribute without any sense of where
 it's going to be okay. Or maybe, I'm surprised I'm the only one that
 finds problem with that.
You are very much not alone. I didn't articulate it very clearly, but I am super not happy with such a new attribute.
Jul 13 2018
next sibling parent Meta <jared771 gmail.com> writes:
On Friday, 13 July 2018 at 21:49:57 UTC, rikki cattermole wrote:
 On 14/07/2018 9:28 AM, Manu wrote:
 I've already contributed other points to this DIP in the way 
 you describe.
 This one however is very strange, and I'm surprised you can 
 find the
 hand-wavy introduction of a new attribute without any sense of 
 where
 it's going to be okay. Or maybe, I'm surprised I'm the only 
 one that
 finds problem with that.
You are very much not alone. I didn't articulate it very clearly, but I am super not happy with such a new attribute.
I'm not crazy about it either, but it may be a necessary evil to avoid breaking code (although it doesn't entirely avoid that, as has been demonstrated).
Jul 13 2018
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/13/18 5:49 PM, rikki cattermole wrote:
 On 14/07/2018 9:28 AM, Manu wrote:
 I've already contributed other points to this DIP in the way you 
 describe.
 This one however is very strange, and I'm surprised you can find the
 hand-wavy introduction of a new attribute without any sense of where
 it's going to be okay. Or maybe, I'm surprised I'm the only one that
 finds problem with that.
You are very much not alone. I didn't articulate it very clearly, but I am super not happy with such a new attribute.
It's a very simple process - implicit is not invented as much as a given. We need to distinguish a constructor from other constructors. The constructor supports attributes. Attributes are a mechanism for distinguishing declarations from other declarations. Ergo, an attribute is the mechanism of choice. Done deal. ===== If we don't like the use of an attribute, it means we somehow failed in defining attributes in the first place. (I don't think we did; attributes as defined in D are brilliant and currently underused.) It's poor language design to define a mechanism for doing a category of Xs and then explicitly avoiding it exactly when the opportunity of doing X arises. From that vantage point, the choice of an attribute to identify implicit copy construction is unassailably obvious, and elucubrated syntax inventions such as " this", "this(ref this x)" are chucklesomely profligate and ridiculously baroque. Andrei
Jul 13 2018
next sibling parent Manu <turkeyman gmail.com> writes:
On Fri, 13 Jul 2018 at 18:00, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 7/13/18 5:49 PM, rikki cattermole wrote:
 On 14/07/2018 9:28 AM, Manu wrote:
 I've already contributed other points to this DIP in the way you
 describe.
 This one however is very strange, and I'm surprised you can find the
 hand-wavy introduction of a new attribute without any sense of where
 it's going to be okay. Or maybe, I'm surprised I'm the only one that
 finds problem with that.
You are very much not alone. I didn't articulate it very clearly, but I am super not happy with such a new attribute.
It's a very simple process - implicit is not invented as much as a given. We need to distinguish a constructor from other constructors. The constructor supports attributes. Attributes are a mechanism for distinguishing declarations from other declarations. Ergo, an attribute is the mechanism of choice. Done deal. ===== If we don't like the use of an attribute, it means we somehow failed in defining attributes in the first place. (I don't think we did; attributes as defined in D are brilliant and currently underused.) It's poor language design to define a mechanism for doing a category of Xs and then explicitly avoiding it exactly when the opportunity of doing X arises. From that vantage point, the choice of an attribute to identify implicit copy construction is unassailably obvious, and elucubrated syntax inventions such as " this", "this(ref this x)" are chucklesomely profligate and ridiculously baroque.
But you surely recognise that D has a lot of intrinsic attributes already, and that's a lot of mental (and visual) baggage to carry around. If we add a new intrinsic attribute, I would want to be sure it's widely useful, because every D user will need to learn about and understand it. It's much easier to learn, and more useful knowledge to have, if it has a broad meaning which solves a general class of problem, than just a marker that you need to remember you have to type in one specific niche location.
Jul 13 2018
prev sibling parent aliak00 <something something.com> writes:
On Saturday, 14 July 2018 at 00:57:14 UTC, Andrei Alexandrescu 
wrote:
 [...]
 chucklesomely profligate and ridiculously baroque.


 Andrei
Hahaha this sentence... amazing! :D I was going to propose auto this(ref A other) {} but nevermind :p Cheers, - Ali
Jul 17 2018
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/13/18 5:28 PM, Manu wrote:
 As I originally said, my feedback is concrete: specify  implicit, this
 DIP depends on it.
The specification of implicit is in the DIP in full: a constructor that takes by reference a qualified typeof(this) and has the implicit attribute will be callable implicitly by the compiler. There is no other meaning of implicit. That completes the spec of implicit. Sadly we got to irreducible positions once again: you and I used different definitions for common terms like "define", "specify", "explain", "contribute", and then you use them to ask questions or make demands, all of which I'm sure you find reasonable. But I am unable to understand them, let alone take them under advisement when working on the DIP. (I did understand your reference to the assignment and will work on that, thanks much.) You will need to forgive me for the scarcity of my future answers - but believe me I will do my best to derive value from your feedback. Andrei
Jul 13 2018
next sibling parent reply Manu <turkeyman gmail.com> writes:
On Fri, 13 Jul 2018 at 17:45, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 7/13/18 5:28 PM, Manu wrote:
 As I originally said, my feedback is concrete: specify  implicit, this
 DIP depends on it.
The specification of implicit is in the DIP in full: a constructor that takes by reference a qualified typeof(this) and has the implicit attribute will be callable implicitly by the compiler. There is no other meaning of implicit. That completes the spec of implicit.
Right, and this is 100% of my concern here. To introduce a new attribute for such a one-off purpose feels like a poor choice, and on those terms I would rather see the feature work with no such attribute (as we've considered in the other fork). If you assess the likelihood of actually breaking code in the wild (I expect it's super slim; data would be nice), you might find that the risk is satisfactory. However, the DIP alludes to a possible future for the attribute, and I think that text is intended to make us feel better about the introduction of the attribute, but I would be a lot more comfortable with a more substantial support of its introduction. Basically, and you already know this; I think it's a weird choice to introduce a new attribute for this one-off case, but as a systemic feature which addresses a general long-standing problem, it feels like a good and logical solution. I think we need some idea if the broader application is even theoretically workable up-front. If there's obvious issues with the idea of deploying implicit generally, then we shouldn't deploy it here, and instead, we should deploy something else here which CAN successfully be generalised in the future. Determining that requires at least a cursory exploration.
Jul 13 2018
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 14/07/2018 1:04 PM, Manu wrote:
 Determining that requires at least a cursory exploration.
Given how many of us are objecting to the syntax, I'm going to place this requirement upon a 'yes' answer by me. That an attempt is made for an alternative syntax discussion. It's a fair request I think.
Jul 14 2018
parent Manu <turkeyman gmail.com> writes:
On Sat., 14 Jul. 2018, 2:00 am rikki cattermole via Digitalmars-d, <
digitalmars-d puremagic.com> wrote:

 On 14/07/2018 1:04 PM, Manu wrote:
 Determining that requires at least a cursory exploration.
Given how many of us are objecting to the syntax, I'm going to place this requirement upon a 'yes' answer by me. That an attempt is made for an alternative syntax discussion. It's a fair request I think.
I just want to reiterate again, I'm not seeking alternative syntax, I just want to know that proposed syntax can work broadly, or if there are any challenges or problems that would restrict it from broad application.

Jul 14 2018
prev sibling parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Saturday, 14 July 2018 at 00:41:37 UTC, Andrei Alexandrescu 
wrote:
 The specification of  implicit is in the DIP in full: a 
 constructor that takes by reference a qualified typeof(this) 
 and has the  implicit attribute will be callable implicitly by 
 the compiler. There is no other meaning of  implicit. That 
 completes the spec of  implicit.
That is the problem: you are using a very generic name ("implicit") to signify both: 1) something very general ("will be callable implicitly by the compiler") and 2) something very specific ("a constructor that takes by reference a qualified typeof(this)") If there is "no other meaning of implicit" (other than the intersection of those two properties) why don't you just call it something like copyctor? On the other hand, if the name is chosen with the hope that the meaning will be generalized in the future ("callable implicitly by the compiler"), why don't you want to at least briefly discuss that more general meaning? What happens if you later conclude that a generic "callable implicitly by the compiler" annotation has semantics that don't quite align with those of this ctor annotation? Do you need to introduce implicitconv? Surely we want the language constructs to be composable and generalizable, and not just quirky one offs that you have to memorize. This seems like a missed opportunity to make sure of that.
Jul 14 2018
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/14/18 5:03 AM, Luís Marques wrote:
 If there is "no other meaning of  implicit" (other than the intersection 
 of those two properties) why don't you just call it something like 
  copyctor?
I'm totally cool with giving the attribute a more obscure name such as copyctor or anything people want really. (What follows is a personal opinion. I think it's better to choose a more general attribute name with reduced initial applicability. Then application of said attribute can be extended to other functions with ease. In contrast, an obscure attribute name is sure to be followed by more obscure attribute names. And don't get me started about inventing new syntax. Regarding the hand-wringing over generality: we have an exceedingly poor record of paralysis of analysis, whereby we'd worry that every design decision potentially locks us out from all other as-of-yet-unchosen design decisions. If history is any indication, this sudden worry about vaguely-promising green pastures of the future is a sign of malady. We want copy construction. Conflating this with a very general schemata for implicit conversion would not be a wise decision in my opinion. I now deeply regret ever telling Razvan to mention future possible directions. This DIP must do implicit copy constructors and do it well, nothing less and nothing more.) Andrei
Jul 14 2018
next sibling parent reply Johan Engelen <j j.nl> writes:
On Saturday, 14 July 2018 at 10:53:17 UTC, Andrei Alexandrescu 
wrote:
 
 I now deeply regret ever telling Razvan to mention future 
 possible directions. This DIP must do implicit copy 
 constructors and do it well, nothing less and nothing more.
Strongly agree with this. In my review on Github I had a few sentences about this, but I removed them because I thought it may be perceived wrong. I find it almost completely irrelevant to add a "future directions" discussion to a DIP. If a DIP is incomplete, then finish it. Other than that, a DIP should stand completely on its own, regardless of speculation on future directions. -Johan
Jul 14 2018
parent rikki cattermole <rikki cattermole.co.nz> writes:
On 14/07/2018 11:49 PM, Johan Engelen wrote:
 On Saturday, 14 July 2018 at 10:53:17 UTC, Andrei Alexandrescu wrote:
 I now deeply regret ever telling Razvan to mention future possible 
 directions. This DIP must do implicit copy constructors and do it 
 well, nothing less and nothing more.
Strongly agree with this. In my review on Github I had a few sentences about this, but I removed them because I thought it may be perceived wrong. I find it almost completely irrelevant to add a "future directions" discussion to a DIP. If a DIP is incomplete, then finish it. Other than that, a DIP should stand completely on its own, regardless of speculation on future directions. -Johan
Really any mention of the "future" in a DIP section wise, should be fairly concrete. I.e. this is already a good design, BUT it may come to pass that this use case is indeed important to support (an acknowledgement to its existence) so here is an idea on how to support it. It doesn't need to be entirely thought out, it just needs to be pretty well thought out and with clear added complexity as to why it isn't part of the original DIP. The example I'll use is my named arguments DIP[0], where I show a feature that could be added to allow renaming of args. However, because I'm unconvinced that such a complex feature is even needed, I don't support it. [0] https://github.com/rikkimax/DIPs/blob/named_args/DIPs/DIP1xxx-RC.md#future-proposals
Jul 14 2018
prev sibling next sibling parent reply docandrew <x x.com> writes:
On Saturday, 14 July 2018 at 10:53:17 UTC, Andrei Alexandrescu 
wrote:
 On 7/14/18 5:03 AM, Luís Marques wrote:
 If there is "no other meaning of  implicit" (other than the 
 intersection of those two properties) why don't you just call 
 it something like  copyctor?
I'm totally cool with giving the attribute a more obscure name such as copyctor or anything people want really. (What follows is a personal opinion. I think it's better to choose a more general attribute name with reduced initial applicability. Then application of said attribute can be extended to other functions with ease. In contrast, an obscure attribute name is sure to be followed by more obscure attribute names. And don't get me started about inventing new syntax. Regarding the hand-wringing over generality: we have an exceedingly poor record of paralysis of analysis, whereby we'd worry that every design decision potentially locks us out from all other as-of-yet-unchosen design decisions. If history is any indication, this sudden worry about vaguely-promising green pastures of the future is a sign of malady. We want copy construction. Conflating this with a very general schemata for implicit conversion would not be a wise decision in my opinion. I now deeply regret ever telling Razvan to mention future possible directions. This DIP must do implicit copy constructors and do it well, nothing less and nothing more.) Andrei
I think in this case, a more obscure name like copyctor is more descriptive. I fear that at some point, a more general attribute like " implicit" will turn into the next "static". To me, implicit smells like one of those keywords that will grow to carry many different meanings in different contexts and just end up overly-broad. -Jon
Jul 16 2018
next sibling parent reply Manu <turkeyman gmail.com> writes:
On Mon., 16 Jul. 2018, 6:00 pm docandrew via Digitalmars-d, <
digitalmars-d puremagic.com> wrote:

 On Saturday, 14 July 2018 at 10:53:17 UTC, Andrei Alexandrescu
 wrote:
 On 7/14/18 5:03 AM, Lu=C3=ADs Marques wrote:
 If there is "no other meaning of  implicit" (other than the
 intersection of those two properties) why don't you just call
 it something like  copyctor?
I'm totally cool with giving the attribute a more obscure name such as copyctor or anything people want really. (What follows is a personal opinion. I think it's better to choose a more general attribute name with reduced initial applicability. Then application of said attribute can be extended to other functions with ease. In contrast, an obscure attribute name is sure to be followed by more obscure attribute names. And don't get me started about inventing new syntax. Regarding the hand-wringing over generality: we have an exceedingly poor record of paralysis of analysis, whereby we'd worry that every design decision potentially locks us out from all other as-of-yet-unchosen design decisions. If history is any indication, this sudden worry about vaguely-promising green pastures of the future is a sign of malady. We want copy construction. Conflating this with a very general schemata for implicit conversion would not be a wise decision in my opinion. I now deeply regret ever telling Razvan to mention future possible directions. This DIP must do implicit copy constructors and do it well, nothing less and nothing more.) Andrei
I think in this case, a more obscure name like copyctor is more descriptive. I fear that at some point, a more general attribute like " implicit" will turn into the next "static". To me, implicit smells like one of those keywords that will grow to carry many different meanings in different contexts and just end up overly-broad.
But that's the point, and the key advantage of the name ;)
Jul 16 2018
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/17/18 12:04 AM, Manu wrote:
 But that's the point, and the key advantage of the name ;)
[:nod:]
Jul 17 2018
prev sibling parent aliak00 <something something.com> writes:
On Tuesday, 17 July 2018 at 04:04:33 UTC, Manu wrote:
 On Mon., 16 Jul. 2018, 6:00 pm docandrew via Digitalmars-d, < 
 digitalmars-d puremagic.com> wrote:

 On Saturday, 14 July 2018 at 10:53:17 UTC, Andrei Alexandrescu 
 wrote:
 On 7/14/18 5:03 AM, Luís Marques wrote:
 If there is "no other meaning of  implicit" (other than the 
 intersection of those two properties) why don't you just 
 call it something like  copyctor?
I'm totally cool with giving the attribute a more obscure name such as copyctor or anything people want really. (What follows is a personal opinion. I think it's better to choose a more general attribute name with reduced initial applicability. Then application of said attribute can be extended to other functions with ease. In contrast, an obscure attribute name is sure to be followed by more obscure attribute names. And don't get me started about inventing new syntax. Regarding the hand-wringing over generality: we have an exceedingly poor record of paralysis of analysis, whereby we'd worry that every design decision potentially locks us out from all other as-of-yet-unchosen design decisions. If history is any indication, this sudden worry about vaguely-promising green pastures of the future is a sign of malady. We want copy construction. Conflating this with a very general schemata for implicit conversion would not be a wise decision in my opinion. I now deeply regret ever telling Razvan to mention future possible directions. This DIP must do implicit copy constructors and do it well, nothing less and nothing more.) Andrei
I think in this case, a more obscure name like copyctor is more descriptive. I fear that at some point, a more general attribute like " implicit" will turn into the next "static". To me, implicit smells like one of those keywords that will grow to carry many different meanings in different contexts and just end up overly-broad.
But that's the point, and the key advantage of the name ;)
Aye! And in this case it really is implicit copy construction. With this attribute in the compiler I can also see a future DIP that deprecates implicit construction and requires an explicit implicit be added to constructors! Which also sounds like a win :D It's not ideal that the implicit attribute does not have a larger discussion around it. But it is nice to something in D where the default is the conservative approach and the more liberal has to be explicitly asked for. And at the same time, at this point it really is an attribute that is only applicable to copy constructors. So how much expansion on that would be enough I wonder? Cheers, - Ali
Jul 17 2018
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/16/18 8:57 PM, docandrew wrote:
 I think in this case, a more obscure name like  copyctor is more 
 descriptive.
On the contrary, it is redundant and uninformative. It applies to exactly a constructor that copies, so it adds no information. " implicit" describes precisely what the attribute does.
Jul 17 2018
prev sibling parent =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Saturday, 14 July 2018 at 10:53:17 UTC, Andrei Alexandrescu 
wrote:
 I think it's better to choose a more general attribute name 
 with reduced initial applicability. Then application of said 
 attribute can be extended to other functions with ease. In 
 contrast, an obscure attribute name is sure to be followed by 
 more obscure attribute names. And don't get me started about 
 inventing new syntax.

 Regarding the hand-wringing over generality: we have an 
 exceedingly poor record of paralysis of analysis, whereby we'd 
 worry that every design decision potentially locks us out from 
 all other as-of-yet-unchosen design decisions. If history is 
 any indication, this sudden worry about vaguely-promising green 
 pastures of the future is a sign of malady. We want copy 
 construction. Conflating this with a very general schemata for 
 implicit conversion would not be a wise decision in my opinion. 
 I now deeply regret ever telling Razvan to mention future 
 possible directions. This DIP must do implicit copy 
 constructors and do it well, nothing less and nothing more.)
I also think a more general attribute is better. I think there's a middle ground between total analysis paralysis and no discussion of concept generality. I had hoped some thought would be given to the implications of implicit but overall I'm still happy, and I trust your judgement. BTW, I would still have brought it up even if the DIP didn't mention future directions :-)
Jul 17 2018
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 Hi everyone!

 I managed to put together a first draft of the DIP for adding the
 copy constructor to the language [1]. If anyone is interested,
 please take a look. Suggestions and comments about technical
 aspects and wording are all welcome.

 Thanks,
 RazvanN

 [1] https://github.com/dlang/DIPs/pull/129
I'd like to see a mention on extern(C++) copy constructors; are they naturally semantically compatible? If not, how will it behave differently when extern(C++) is applied (ie, like C++)? Normal constructors and destructors change semantics in the presence of extern(C++).
Jul 12 2018
prev sibling parent reply xenon325 <anm programmer.net> writes:
 From the DIP:
 The copy constructor declaration will be recognized by the 
 parser when the tokens  , implicit, this are encountered 
 exactly in this order
Regarding "exactly in this order". The code below would be allowed and define copy c'tor for `A` and usual c'tor for `B` ? struct implicit{} struct A { safe implicit this(ref A) {} } struct B { implicit safe this(ref B) {} }
Jul 13 2018
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 7/13/18 12:06 PM, xenon325 wrote:
  From the DIP:
 The copy constructor declaration will be recognized by the parser when 
 the tokens  , implicit, this are encountered exactly in this order
Regarding "exactly in this order". The code below would be allowed and define copy c'tor for `A` and usual c'tor for `B` ?     struct implicit{}     struct A {         safe implicit this(ref A) {}     }     struct B {         implicit safe this(ref B) {}     }
We'll change that part to accept the standard attribute syntax.
Jul 13 2018