[Closed] DeepCopy maintaining Pointer to Value?
I have an array of structs, of which some have an array property. when I create a deepCopy of this ‘array of structs’ the properties which are arrays are still pointing to the same array value…
With simple properties it’s fine.
struct myTest
(
name = "node1",
testVal = 5.0,
testArray = #()
)
myAR = #()
s = myTest testArray:#(1)
append myAR s
arList = #()
p = (deepcopy myAR)
insertItem (p) arList 1
s.testVal = 10.0
p = (deepcopy myAR)
insertItem (p) arList 1
arList
Looking at the result…
#(#((myTest name:"node1" testVal:10.0 testArray:#(1))), #((myTest name:"node1" testVal:5.0 testArray:#(1))))
… the testVal has change on the 1st item we’ve changed before it has been inserted into the array in the 1st position.
struct myTest
(
name = "node1",
testVal = 5.0,
testArray = #()
)
myAR = #()
s = myTest testArray:#(1)
append myAR s
arList = #()
p = (deepcopy myAR)
insertItem (p) arList 1
s.testVal = 10.0
p = (deepcopy myAR)
insertItem (p) arList 1
append s.testArray 1
p = (deepcopy myAR)
insertItem (p) arList 1
arList
Result…
#(#((myTest name:"node1" testVal:10.0 testArray:#(1, 1))), #((myTest name:"node1" testVal:10.0 testArray:#(1, 1))), #((myTest name:"node1" testVal:5.0 testArray:#(1, 1))))
I appended ‘1’ to s but that also got appended to all the other array values within the arList array…
Any ideas???
this is known for me issue. it’s why i added to my mxs extension two new functions: deepCopyArray and deepCopyStruct.
so my suggestion is to write your own recursive copy function which solves this issue.
That should work.
upd. Struct copy should be recursive indeed.
struct myTest
(
name = "node1",
testVal = 5.0,
testArray = #()
)
fn deepStructCopy struct_ = (
copyStruct = copy struct_
for prop in getpropnames copyStruct where classof (arr = getproperty copyStruct prop) == Array do (
setProperty copyStruct prop (deepCopy arr)
)
copyStruct
)
fn deepArrayCopy arr = (
copyArr = deepCopy arr
for i=1 to copyArr.count where superclassOf copyArr[i] == StructDef do copyArr[i] = ::deepStructCopy copyArr[i]
copyArr
)
myAR = #()
s = myTest testArray:#("one")
append myAR s
arList = #()
p = deepArrayCopy myAR
insertItem (p) arList 1
s.testVal = 10.0
p = deepArrayCopy myAR
insertItem (p) arList 1
append s.testArray "two"
p = deepArrayCopy myAR
insertItem (p) arList 1
arList[1].testVal += 15
arList[1][1].testArray[1] = 666
arList[2][1].testArray[2] = 333
arList
Thanks guys, that’s not me going crazy then…
continuing going crazy is the other annoying factor… what if the array of structs has copies in it that you don’t want to lose…
struct myTest
(
name = "node1",
testVal = 5.0,
testArray = #()
)
s1 = myTest testArray:#(1)
s2 = myTest name:"node2" testArray:#(3)
AR_NodesBuffer = #()
testAR = #(s1,s1,s2,s2,s1)
you follow my tracks
it doesn’t matter if you use a struct or not. with deepCopy you always lose values instancing:
a = [1,1,1]
b = a
aa = #(a,b)
bb = deepcopy aa
bb[1].x = 2
bb
aa[1].x = 2
aa
as you can see after deepcopy elements of array bb are not the same values anymore.
i think we have to live with it, just know about this behavior
Here is a simplified and mxs version of my deep_copy…
struct deep_copy_struct
(
fn copy_str src =
(
new = copy src
for p in getpropnames src do
(
v = getproperty src p
if iskindof v array then setproperty new p (this.copy_arr v)
else if isstruct v do setproperty new p (this.copy_str v)
)
new
),
fn copy_arr arr =
(
new = deepcopy arr
for k=1 to arr.count do
(
v = arr[k]
if iskindof v array then new[k] = this.copy_arr v
else if isstruct v do new[k] = this.copy_str v
)
new
),
fn copy_val val =
(
if iskindof val array then this.copy_arr val
else if isstruct val then this.copy_str val
else copy val
)
)
/*
struct AA (list = #())
a = #(1,3,4)
aaa = AA list:a
dc = deep_copy_struct()
bbb = deepcopy #(aaa) -- NOT RIGHT
--bbb = dc.copy_val #(aaa) -- SHOULD BE RIGHT
bbb[1].list[1] = 6
aaa
*/
Great stuff Denis, this stuff is gold. Mind if I write a blog about this and quote your code?