Jump to content

Deepcopy: Difference between revisions

Added Wren
m (Update last tested version number. Removed imports which are now useless.)
(Added Wren)
Line 2,074:
For objects (as introduced in Tcl 8.6), there is a command to create a copy:
<lang tcl>set copiedObject [oo::copy $originalObject]</lang>
 
=={{header|Wren}}==
{{libheader|Wren-seq}}
{{libheader|Wren-trait}}
Wren does not have any built-in facilities for deep-copying an object and you therefore have to write your own method to do this.
 
However, using the above module, a class can inherit from the Cloneable or CloneableSeq abstract class and override its clone() method. Knowing that objects have such a method is useful when cloning other objects which contain them as fields or nested fields.
 
Note though that, since Wren is dynamically typed, it may be impractical or impossible to deep-copy generic objects because, if an object does not have a clone() method, all that can be done is to return the argument itself which, unless it is a built-in immutable type, will simply be a reference to the original.
 
In the following example, we attempt to deep-copy a custom type, MyMap, which wraps the built-in generic Map type. This succeeds here because of the types of values used but wouldn't succeed if a Map value were, say, some user-defined type which didn't have a clone() method.
<lang ecmascript>import "/trait" for Cloneable, CloneableSeq
import "/seq" for Lst
 
class MyMap is Cloneable {
construct new (m) {
if (m.type != Map) Fiber.abort("Argument must be a Map.")
_m = m
}
 
m { _m }
 
toString { _m.toString }
 
clone() {
// Map keys are always immutable built-in types so we only need to worry about
// their values which can be anything.
var m2 = {}
for (me in _m) {
var v = me.value
m2[me.key] = (v is List) ? Lst.clone(v) :
(v is Cloneable || v is CloneableSeq) ? v.clone() : v
}
return MyMap.new(m2)
}
}
 
var my = MyMap.new({"a": 0, "b": 1, "c": [2, 3], "d": MyMap.new({"e": 4})})
var my2 = my.clone()
System.print("Before any changes:")
System.print(" my = %(my)")
System.print(" my2 = %(my2)")
// now change my2
my2.m["a"] = 5
my2.m["b"] = 6
my2.m["c"][0] = 7
my2.m["c"][1] = 8
my2.m["d"].m["e"] = 9
my2.m["d"].m["f"] = 10
System.print("\nAfter changes to my2:")
System.print(" my = %(my)")
System.print(" my2 = %(my2)")</lang>
 
{{out}}
<pre>
Before any changes:
my = {c: [2, 3], d: {e: 4}, b: 1, a: 0}
my2 = {c: [2, 3], d: {e: 4}, b: 1, a: 0}
 
After changes to my2:
my = {c: [2, 3], d: {e: 4}, b: 1, a: 0}
my2 = {c: [7, 8], d: {e: 9, f: 10}, b: 6, a: 5}
</pre>
 
{{omit from|Haskell}}
9,490

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.