Deepcopy -- bug or my misunderstanding?

107 views
Skip to first unread message

Stuart Brorson

unread,
Jun 5, 2013, 8:04:15 AM6/5/13
to julia...@googlegroups.com
Hi --

Perhaps I don't know what I am doing, but I have found some deepcopy()
behavior which seems wrong.

Refer to the below code. This is a boiled-down version of behavior I
am seeing in my project code. I create an underlying type, named foo,
containing a vector. Then I wrap it in an upper layer type, named
bar, which is also a vector. (That is, bar is a vector of foos, and
each foo contains a vector of ints.)

Next I create an instance of bar named S. Then I make a deepcopy of S
(called u) and assign things to it. I expect that since I made the
deepcopy, S should not change. However it does. Refer to the session
log which I have also scraped below.

As an aside, when I deepcopy the individual element of foo, then I get
the expected behavior (i.e. S is unchnaged).

Have I misunderstood something? Or is this a bug?

Stuart


----------------------- Code ------------------------------
type foo
a::Int64
b::Vector{Int64}
end

immutable bar
t::Vector{foo}
end

# Constructor
function bar(x::foo...)
t = bar([x...])
end

X = foo(1, [11, 12])
Y = foo(3, [13, 14])

S = bar(X, Y)

S.t[1].b[1]

# u = deepcopy(S.t[1].b[1]) # This works (i.e. S is unchanged)
u = deepcopy(S) # This fails (i.e. S changes)
u.t[1].b[1] = 999
u.t[1].b[1]

S.t[1].b[1]

-------------------- Sesssion log ---------------------
[sdb@localhost examples]$ ../julia
_
_ _ _(_)_ | A fresh approach to technical computing
(_) | (_) (_) | Documentation: http://docs.julialang.org
_ _ _| |_ __ _ | Type "help()" to list help topics
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 0.2.0-1781.r0c597ed5
_/ |\__'_|_|_|\__'_| | Commit 0c597ed56e 2013-06-02 17:05:33
|__/ |

julia> type foo
a::Int64
b::Vector{Int64}
end

julia>

julia> immutable bar
t::Vector{foo}
end

julia>

julia> # Constructor

julia> function bar(x::foo...)
t = bar([x...])
end
bar

julia>

julia> X = foo(1, [11, 12])
foo(1,[11, 12])

julia> Y = foo(3, [13, 14])
foo(3,[13, 14])

julia>

julia> S = bar(X, Y)
bar([foo(1,[11, 12]), foo(3,[13, 14])])

julia>

julia> S.t[1].b[1]
11

julia>

julia> # u = deepcopy(S.t[1].b[1]) # This works (i.e. S is unchanged)

julia> u = deepcopy(S) # This fails (i.e. S changes)
bar([foo(1,[11, 12]), foo(3,[13, 14])])

julia> u.t[1].b[1] = 999
999

julia> u.t[1].b[1]
999

julia>

julia> S.t[1].b[1]
999


Tim Holy

unread,
Jun 5, 2013, 8:35:26 AM6/5/13
to julia...@googlegroups.com
It's a tricky case, and I think could be viewed as a bug, but the behavior
makes quite a bit of sense from a certain perspective. The key observation is
that if you change bar from immutable to mutable (type), then it works as
you're expecting.

What is happening here is that immutables are values in the same way an
integer is a value. When you copy an integer from one memory location to
another, you just take what you find in the source location and copy it into
the destination. Similarly, since bar is immutable, the prescription is to
take what you find in the source memory location (here, what is effectively the
pointer to a particular memory location storing the data in t) and copy it
into the destination. Hence S and u share the vector t, despite your
intentions.

Presumably deepcopy could be changed to work the way you expect, but there is
a sense in which that might violate the spirit of immutables.

Maybe we need "reallydeepcopy"? :-)

--Tim

Stuart Brorson

unread,
Jun 5, 2013, 1:17:21 PM6/5/13
to julia...@googlegroups.com
Tim,

Thanks. Yes, you are right, when I declare bar to be a type instead
of immutable, then I get the expected behavior. See session log
below.

I think the behavior w.r.t. immutable is buggish. Should I file an
issue? Or does the team want to think about it for awhile?

Stuart

[sdb@localhost examples]$ ../julia
_
_ _ _(_)_ | A fresh approach to technical computing
(_) | (_) (_) | Documentation: http://docs.julialang.org
_ _ _| |_ __ _ | Type "help()" to list help topics
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 0.2.0-1781.r0c597ed5
_/ |\__'_|_|_|\__'_| | Commit 0c597ed56e 2013-06-02 17:05:33
|__/ |

julia> type foo
a::Int64
b::Vector{Int64}
end

julia>

julia> type bar
t::Vector{foo}
end

julia>

julia> # Constructor

julia> function bar(x::foo...)
t = bar([x...])
end
bar

julia>

julia> X = foo(1, [11, 12])
foo(1,[11, 12])

julia> Y = foo(3, [13, 14])
foo(3,[13, 14])

julia>

julia> S = bar(X, Y)
bar([foo(1,[11, 12]), foo(3,[13, 14])])

julia>

julia> S.t[1].b[1]
11

julia>

julia> u = deepcopy(S)
bar([foo(1,[11, 12]), foo(3,[13, 14])])

julia> u.t[1].b[1] = 999
999

julia> u.t[1].b[1]
999

julia>

julia> S.t[1].b[1]
11

julia>

Stefan Karpinski

unread,
Jun 5, 2013, 1:19:31 PM6/5/13
to Julia Users
Yes, do file an issue. This should be changed.

Stuart Brorson

unread,
Jun 5, 2013, 2:50:58 PM6/5/13
to Julia Users
You got it! Bug no is 3301.

Cheers,

Stuart
Reply all
Reply to author
Forward
0 new messages