Every language
13 linguagens, copy-ready. One at a time with syntax highlighting, or all inline.
JSJavaScript
// spread is SHALLOW — one level only. This is the real deep clone:
const copy = structuredClone(value); // Dates, Maps, Sets, cycles: all keptThe old JSON.parse(JSON.stringify(value)) trick loses Dates (→ strings), undefined, Map/Set, and dies on cycles. structuredClone (all runruns since 2022) handles them.
TSTypeScript
declare const state: { user: { name: string; tags: string[] } };
const copy: typeof state = structuredClone(state); // typed as T in, T out
copy.user.tags.push('x'); // original untouchedstructuredClone's lib type is <T>(value: T): T — the clone keeps the compile-time shape. Functions cannot be cloned; the call throws on them.
GoGo
// no stdlib deep copy — the data-only struct roundtrip:
func deepClone[T any](v T) (T, error) {
var out T
b, err := json.Marshal(v)
if err != nil {
return out, err
}
err = json.Unmarshal(b, &out)
return out, err
}The JSON hop drops unexported fields and needs the struct exported + serializable. Graphs with cycles or func fields: write the copy by hand.
RsRust
#[derive(Clone)]
struct Config {
name: String,
nested: Vec<String>,
}
let copy = original.clone(); // DEEP: every owned value duplicatedThe inversion: Rust clones deep by default — sharing must be explicit (Rc/Arc make .clone() bump a refcount instead). The question this recipe asks barely exists here.
PHPPHP
// nested ARRAYS copy deep on assignment (value semantics)…
$b = $a; // deep for nested arrays
// …but objects inside are shared references:
$clone = unserialize(serialize($object)); // the classic deep cloneclone $obj copies one level; nested objects stay shared. serialize/unserialize handles the graph but breaks closures and resources.
PyPython
import copy
deep = copy.deepcopy(nested) # graphs, cycles handled
# all of these are SHALLOW for nested mutables:
# b = a · b = a[:] · b = list(a) · b = dict(a) · b = a.copy()Slicing a list of lists copies the outer list; the inner lists are shared objects. deepcopy also memoizes, so shared sub-objects stay shared in the clone.
C++C++
// value semantics: the compiler-generated copy constructor deep-copies
// every member that itself has value semantics:
struct Config {
std::string name; // deep: a new string
std::vector<std::string> tags; // deep: a new vector of new strings
};
auto copy = original; // DEEP by construction — no clone() call anywhereThe rule is deep-by-construction: std::string, std::vector, and every RAII type clone correctly inside the default copy constructor. A raw pointer member stays SHARED between copies — which is why raw owning pointers are banned in modern C++; hold members by value or by smart pointer.
C#C#
using System.Text.Json;
var copy = JsonSerializer.Deserialize<User>(
JsonSerializer.Serialize(original));Record with-expressions (original with { ... }) are shallow, like Kotlin's copy(). The JSON hop needs parameterless constructors or JsonSerializerOptions with custom factory.
JvJava
// Object.clone() is shallow and effectively deprecated.
// The modern Java answer: make it immutable — then shallow IS deep.
record Address(String city) {}
record User(String name, Address address) {}
User copy = new User(original.name(), original.address());Immutable records end the question: no mutation is possible, so sharing nested values is safe and 'cloning' means copying the references you want to change.
SwSwift
// STRUCTS: assignment IS a deep copy — value semantics
var copy = original // nested structs and arrays fully independent
// CLASSES are reference types — a class tree needs explicit cloningOne language, both answers: struct copies deep (arrays/strings are copy-on-write underneath, so it is cheap), class instances share. Prefer structs; the compiler does the rest.
KtKotlin
data class User(val name: String, val tags: List<String>)
val copy = original.copy(name = "Ada") // SHALLOW: tags list is sharedTHE Kotlin trap: data-class copy() is a shallow field-by-field copy. Nested mutables stay shared — combine with a deep clone of the fields you will mutate.
RbRuby
shallow = obj.dup # one level
deep = Marshal.load(Marshal.dump(obj)) # the stdlib deep cloneMarshal roundtrip handles nested state but raises on procs, singletons, and IO objects. dup keeps frozen state; clone copies it.
ZigZig
// assignment copies the struct's bytes — pointers and slices stay shared.
// For plain-data structs, the JSON roundtrip is the honest stdlib deep copy:
const std = @import("std");
fn deepClone(comptime T: type, alloc: std.mem.Allocator, value: T) !T {
var buf = std.ArrayList(u8).init(alloc);
defer buf.deinit();
try std.json.stringify(value, .{}, buf.writer());
const parsed = try std.json.parseFromSlice(T, alloc, buf.items, .{});
defer parsed.deinit(); // copies out below keep it valid
return parsed.value;
}parseFromSlice returns an arena-owned value — returning parsed.value by value copies it out (safe for data structs, not for pointers the arena owns). Slices inside the struct point INTO the arena: real clones need explicit allocation.