Discussion:
Copy constructor in D. Why it is necessary to have it.
(too old to reply)
Eldar Insafutdinov
2008-09-30 19:37:50 UTC
Permalink
http://www.everfall.com/paste/id.php?m46jrb36o7qu

This is a short example. It has all the comments inside. Since "in" keyword tells the compiler to make a copy of an class object - a new object is created. But constructor for this object is not called(you can check it). In my opinion it is a big issue and needs to be improved.
Denis Koroskin
2008-09-30 19:54:57 UTC
Permalink
On Tue, 30 Sep 2008 23:37:50 +0400, Eldar Insafutdinov
Post by Eldar Insafutdinov
http://www.everfall.com/paste/id.php?m46jrb36o7qu
This is a short example. It has all the comments inside. Since "in"
keyword tells the compiler to make a copy of an class object - a new
object is created.
No, that's not true. No heap activity is done under the hood, a copy of
/pointer/ is passed (as opposed to a copy of /instance/).
In means that changes to the variable won't be visible to the caller:

void foo(in TreeIter it)
{
it = null; // makes local change
}

An important thing to note is that `in` is not recursive (as const or
invariant).
Post by Eldar Insafutdinov
But constructor for this object is not called(you can check it). In my
opinion it is a big issue and needs to be improved.
No, it shouldn't generate heap activity unless really needed. In this case
do the following:

void foo(const(TreeIter) it)
{
auto itCopy = it.clone();
// do whatever you wish with a copy.
}

But in general, a const reference should be enough to you.
Eldar Insafutdinov
2008-09-30 20:18:13 UTC
Permalink
Post by Denis Koroskin
On Tue, 30 Sep 2008 23:37:50 +0400, Eldar Insafutdinov
Post by Eldar Insafutdinov
http://www.everfall.com/paste/id.php?m46jrb36o7qu
This is a short example. It has all the comments inside. Since "in"
keyword tells the compiler to make a copy of an class object - a new
object is created.
No, that's not true. No heap activity is done under the hood, a copy of
/pointer/ is passed (as opposed to a copy of /instance/).
In my particular case changes are made to the data behind the pointer - and they are not copied because, only pointer itself is copied. In C++ when you call a function like this:
foo(TClass instance);
copy constructor is called to create a proper copy of an object. "in" keyword means exactly the same I guess? it makes a local copy of an object, so that variable is not supposed to be modified. But in my case since I use a binding to a C-library - the real data is behind the pointer. foo() cannot modify the class fields themself, but since pointer both in variable and local copy point to the same data - the semantics of "in" doesn't work.
Post by Denis Koroskin
Post by Eldar Insafutdinov
auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
bearophile
2008-09-30 20:34:58 UTC
Permalink
Post by Eldar Insafutdinov
Post by Denis Koroskin
auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance.

Instead of "clone()" I suggest "dup", that's the standard in D.

Bye,
bearophile
BCS
2008-09-30 20:38:17 UTC
Permalink
Reply to bearophile,
Post by bearophile
Post by Eldar Insafutdinov
Post by Denis Koroskin
auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing
appropriate keyword. I should only write a copy constructor for my
data and let to do the rest to the compiler.
In D all objects are managed by reference.
BTW note that structs ARE pass by value.
Bill Baxter
2008-09-30 20:39:55 UTC
Permalink
Post by bearophile
Post by Eldar Insafutdinov
Post by Denis Koroskin
auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance.
Instead of "clone()" I suggest "dup", that's the standard in D.
It has been pointed out though, that dup is a "shallow copy" in D's
built-in usage. If you want a deep copy operation, there is no
precedent in the base language, I believe. Clone is a good one to
standardize on for deep copies, I think.

--bb
bearophile
2008-09-30 20:55:12 UTC
Permalink
Post by Bill Baxter
It has been pointed out though, that dup is a "shallow copy" in D's
built-in usage. If you want a deep copy operation, there is no
precedent in the base language, I believe. Clone is a good one to
standardize on for deep copies, I think.
I see.
Probably the more readable & intuitive names are "copy" and "deepcopy". But "dup" is already present, so it has to be accepted, I presume.
What about "deepdup" for the deep version instead? :-) It's more easy to remember its meaning (and I presume it's not that commonly used to deserve a very short name).

Bye,
bearophile
Bill Baxter
2008-09-30 21:06:11 UTC
Permalink
Post by bearophile
Post by Bill Baxter
It has been pointed out though, that dup is a "shallow copy" in D's
built-in usage. If you want a deep copy operation, there is no
precedent in the base language, I believe. Clone is a good one to
standardize on for deep copies, I think.
I see.
Probably the more readable & intuitive names are "copy" and "deepcopy". But "dup" is already present, so it has to be accepted, I presume.
What about "deepdup" for the deep version instead? :-)
Heh, made me think .deeppoop when I first saw that.
Post by bearophile
It's more easy to remember its meaning (and I presume it's not that commonly used to deserve a very short name).
I like clone. It's used pretty commonly in other languages. I'd
rather not follow up one slightly odd-ball name with an even more
bizarre one. But it's not gonna be anything more than a convention
anyway, so you're free to name it .deepdup if you like in your
libraries.

--bb
bearophile
2008-09-30 21:53:32 UTC
Permalink
Post by Bill Baxter
I like clone. It's used pretty commonly in other languages.
Java?
Post by Bill Baxter
I'd rather not follow up one slightly odd-ball name with an even more
bizarre one. But it's not gonna be anything more than a convention
anyway, so you're free to name it .deepdup if you like in your
libraries.
If the D convention is clone I'll use clone! :-) Using different conventions is generally bad.

Bye,
bearophile
Bill Baxter
2008-09-30 22:00:53 UTC
Permalink
Post by bearophile
Post by Bill Baxter
I like clone. It's used pretty commonly in other languages.
Java?
I've seen it used in C++ libs too.
Post by bearophile
Post by Bill Baxter
I'd rather not follow up one slightly odd-ball name with an even more
bizarre one. But it's not gonna be anything more than a convention
anyway, so you're free to name it .deepdup if you like in your
libraries.
If the D convention is clone I'll use clone! :-) Using different conventions is generally bad.
There is no real convention at this point. Has anyone seen a D
library that contains a way to make deep copies of its objects?

--bb
KennyTM~
2008-10-01 08:20:42 UTC
Permalink
Post by Bill Baxter
Post by bearophile
Post by Bill Baxter
It has been pointed out though, that dup is a "shallow copy" in D's
built-in usage. If you want a deep copy operation, there is no
precedent in the base language, I believe. Clone is a good one to
standardize on for deep copies, I think.
I see.
Probably the more readable & intuitive names are "copy" and "deepcopy". But "dup" is already present, so it has to be accepted, I presume.
What about "deepdup" for the deep version instead? :-)
Heh, made me think .deeppoop when I first saw that.
Post by bearophile
It's more easy to remember its meaning (and I presume it's not that commonly used to deserve a very short name).
I like clone. It's used pretty commonly in other languages. I'd
rather not follow up one slightly odd-ball name with an even more
bizarre one. But it's not gonna be anything more than a convention
anyway, so you're free to name it .deepdup if you like in your
libraries.
--bb
I use .clone also, but the difference in meaning between .clone and .dup
may not be clear enough to say the former is a deep copy but the latter
is shallow.

Ouch, but we have invariant vs const already, so maybe it's OK. /sarcasm
Walter Bright
2008-10-01 09:33:56 UTC
Permalink
Post by Bill Baxter
But it's not gonna be anything more than a convention
anyway, so you're free to name it .deepdup if you like in your
libraries.
We've been informally calling it "deepdup". The advantage of that is it
is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
bearophile
2008-10-01 11:22:03 UTC
Permalink
Post by Walter Bright
We've been informally calling it "deepdup". The advantage of that is it
is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be understood much better than "clone".

On the other hand there are some name changes that can improve D2:
1) invariant => immutable
2) .length => .size
3) .dup => .copy
4) .deepdup => deepcopy

1 and 2) are surely improvements.

3) "dup" is used quite commonly, so it deserves a short name, but "copy" is just one character longer, it isn't an abbreviation, and it's more readable, so I think it's not bad.

And 4) is just the natural extension of the name 3). It doesn't deserve a very short name because it's not used often, so it's better to make it as readable as possible.

Bye,
bearophile
Steven Schveighoffer
2008-10-01 13:45:52 UTC
Permalink
Post by bearophile
Post by Walter Bright
We've been informally calling it "deepdup". The advantage of that is it
is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be
understood much better than "clone".
1) invariant => immutable
Yes
Post by bearophile
2) .length => .size
No. Size can imply the memory size, so an array of ints, I might expect
size to return 4*length.
Post by bearophile
3) .dup => .copy
either works for me.
Post by bearophile
4) .deepdup => deepcopy
either works for me.
Post by bearophile
3) "dup" is used quite commonly, so it deserves a short name, but "copy"
is just one character longer, it isn't an abbreviation, and it's more
readable, so I think it's not bad.
character length is not as important as clarity, but dup seems pretty clear
to me. If it were copy vs. duplicate, I'd go with copy for brevity, but
either is fine.

-Steve
Sean Kelly
2008-10-01 17:23:40 UTC
Permalink
Post by bearophile
Post by Walter Bright
We've been informally calling it "deepdup". The advantage of that is it
is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be understood much better than "clone".
Everyone has a different opinion :-)
Post by bearophile
1) invariant => immutable
Seconded.
Post by bearophile
2) .length => .size
No. To me, 'size' should return the number of bytes of something, not
the number of elements. 'length' is appropriate for what's being returned.
Post by bearophile
3) .dup => .copy
.dup is fine as is, and I think it should always perform a deep copy.
With D going the direction it is, shallow copies are of limited use and
can therefore be called .shallow or something.
Post by bearophile
4) .deepdup => deepcopy
Invalid, assuming #3 above.


Sean
Sergey Gromov
2008-10-02 20:51:19 UTC
Permalink
Wed, 01 Oct 2008 10:23:40 -0700,
Post by Sean Kelly
Post by bearophile
3) .dup => .copy
.dup is fine as is, and I think it should always perform a deep copy.
With D going the direction it is, shallow copies are of limited use and
can therefore be called .shallow or something.
Deep copy is not possible without knowing the object structure. How
about opDup? :)
Bill Baxter
2008-10-02 21:15:00 UTC
Permalink
Post by Sergey Gromov
Wed, 01 Oct 2008 10:23:40 -0700,
Post by Sean Kelly
Post by bearophile
3) .dup => .copy
.dup is fine as is, and I think it should always perform a deep copy.
With D going the direction it is, shallow copies are of limited use and
can therefore be called .shallow or something.
Deep copy is not possible without knowing the object structure. How
about opDup? :)
How would that differ from a function called dup?
Anyway, copying objects is definitely another place D's story is a little weak.
The class/struct distinction does relieve some of the pressure, but
eventually you will run into situations where you want to copy an
object.

In my code I've been creating polymorphic copy(Type obj) functions
that copy from obj to this. Then implementing dup in terms of copies
like:

Type dup() {
ret = new Type;
ret.copy(this);
return ret;
}

The language could potentially help by automating some of that and
calling an opCopy automatically when "dup" is invoked.
But the above isn't terribly onerous.

Just to be explicit about my understanding of the issues: The basic
problem with just having a dup() is that if Deriv derives from Base
and both implement dup, there's no way for Deriv's dup to use Base's
dup. Both will try to allocate a whole object of their own type. So
dup can't usefully be extended using virtual functions. A copy
function can, though.

void Deriv.copy(Deriv obj) {
// copy from objs fields
this.xxx = obj.xxx ;
// copy super's fields
super.copy(obj);
}

Copying and construction in C++ always seems to be good topics for
tricky interview questions, so there's likely more involved than what
I've just said.

--bb
bearophile
2008-10-02 21:58:26 UTC
Permalink
Post by Sergey Gromov
Deep copy is not possible without knowing the object structure. How
about opDup? :)
An opCopy() / opDeepcopy looks useful (not opDup because in D special names are named about their meaning and not their syntax).
In Python there are the standard special methods __copy__ and __deepcopy__ for that purpose (during deepcopying the system takes care of eventually present loops, this will be important in D too).

Related to the copy, a opGetstate() / opSetstate() may be useful to serialize / deserialize objects on disk.
In Python they of named __setstate__ / __getstate__, when they are present the pickle function uses them, otherwise it just reads/writes all the object attributes.

Bye,
bearophile
Bent Rasmussen
2008-10-01 19:41:28 UTC
Permalink
You have a procedural mind, Bearophile ;-)

"bearophile" <bearophileHUGS at lycos.com> skrev i meddelelsen
Post by bearophile
Post by Walter Bright
We've been informally calling it "deepdup". The advantage of that is it
is fairly hard to misinterpret. Nobody liked my ".dupofearl" idea.
I agree that given the "dup", then then meaning of "deepdup" can be
understood much better than "clone".
1) invariant => immutable
2) .length => .size
3) .dup => .copy
4) .deepdup => deepcopy
1 and 2) are surely improvements.
3) "dup" is used quite commonly, so it deserves a short name, but "copy"
is just one character longer, it isn't an abbreviation, and it's more
readable, so I think it's not bad.
And 4) is just the natural extension of the name 3). It doesn't deserve a
very short name because it's not used often, so it's better to make it as
readable as possible.
Bye,
bearophile
bearophile
2008-10-01 21:17:13 UTC
Permalink
Post by Bent Rasmussen
You have a procedural mind, Bearophile ;-)
Is this a good or bad thing? :-)

Bye,
bearophile (lowercase)
Bent Rasmussen
2008-10-02 16:36:21 UTC
Permalink
I'm talking out of my ass, as superdan would say, Bearophile*. Although your
preferred names sound a "tad" more "procedural" to me. Ass-talking "off" :-)

- bent*

* It's a variable name!

"bearophile" <bearophileHUGS at lycos.com> skrev i meddelelsen
Post by bearophile
Post by Bent Rasmussen
You have a procedural mind, Bearophile ;-)
Is this a good or bad thing? :-)
Bye,
bearophile (lowercase)
Tom S
2008-10-01 22:48:28 UTC
Permalink
Post by Walter Bright
Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ...
--
Tomasz Stachowiak
http://h3.team0xf.com/
h3/h3r3tic on #D freenode
Bill Baxter
2008-10-02 00:17:23 UTC
Permalink
Post by Tom S
Post by Walter Bright
Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ...
I think it's because it was too hard to tell if it was dup-of-earl or
dup-o-fear---l.

Beware! The Dup 'o Fear..l awaits you all
with nasty big pointy teeth.

--bb
Walter Bright
2008-10-02 21:26:45 UTC
Permalink
Post by Bill Baxter
Post by Tom S
Post by Walter Bright
Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ...
I think it's because it was too hard to tell if it was dup-of-earl or
dup-o-fear---l.
Beware! The Dup 'o Fear..l awaits you all
with nasty big pointy teeth.
--bb
And when I dup you
You will be my Duped, deep-duped of Earl
We'll walk through my dupdom
And the bits we will share
Tom S
2008-10-02 23:15:59 UTC
Permalink
Post by Walter Bright
On Thu, Oct 2, 2008 at 7:48 AM, Tom S
Post by Tom S
Post by Walter Bright
Nobody liked my ".dupofearl" idea.
Why? :( Nothing can stop the .dupofearl ...
I think it's because it was too hard to tell if it was dup-of-earl or
dup-o-fear---l.
Beware! The Dup 'o Fear..l awaits you all
with nasty big pointy teeth.
--bb
And when I dup you
You will be my Duped, deep-duped of Earl
We'll walk through my dupdom
And the bits we will share
Wow! You may not have a beard/mustache (
http://www.alenz.org/mirror/khason/why-microsoft-can-blow-off-with-c.html
), but D is destined to succeed simply because your nerdiness level
beats everyone ;) Too bad you couldn't come to the Tango Conference...
--
Tomasz Stachowiak
http://h3.team0xf.com/
h3/h3r3tic on #D freenode
Eldar Insafutdinov
2008-09-30 21:01:35 UTC
Permalink
Post by bearophile
Post by Eldar Insafutdinov
Post by Denis Koroskin
auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance.
Instead of "clone()" I suggest "dup", that's the standard in D.
Bye,
bearophile
Ah ok, so when using "in" with class objects - it means that I can't modify the reference itself. So no copy occured. I was wrong.
Bill Baxter
2008-09-30 21:09:20 UTC
Permalink
On Wed, Oct 1, 2008 at 6:01 AM, Eldar Insafutdinov
Post by Eldar Insafutdinov
Post by bearophile
Post by Eldar Insafutdinov
Post by Denis Koroskin
auto itCopy = it.clone();
Why copy it manually if language tends to do it so by providing appropriate keyword. I should only write a copy constructor for my data and let to do the rest to the compiler.
In D all objects are managed by reference. So when you copy automatically, you are just copying its reference, that's a pointer fully managed by the GC. If you want a copy of the data of an object you ask so to it. This simplifies collections and reduces the number of copies, improving performance.
Instead of "clone()" I suggest "dup", that's the standard in D.
Bye,
bearophile
Ah ok, so when using "in" with class objects - it means that I can't modify the reference itself. So no copy occured. I was wrong.
In D1 'in' is a no-op. It just means pass the parameter normally.
Which for classes means you're actually passing a pointer/reference to
the class.

I've done very little with D2, but in D2 I think 'in' on a parameter
means 'const'. Or maybe "const final".

--bb
Continue reading on narkive:
Loading...