Expand/Shrink

deep_copy

Definition: object x = deep_copy(object x, integer depth=-1, bool bIfNeeded=false)
Description: Create an independent clone of x, that does not rely on subsequent copy-on-write semantics.

x: the object to clone.
depth: (optional, experimental) the depth to clone, defaults to full.
bIfNeeded: (optional, experimental) avoids a clone if the refcount of x is already 1.
pwa/p2js: Introduced specifically for p2js, for more details see the Incompatibilities section of that documentation.
Comments: Phix has pass by reference with copy on write semantics whereas JavaScript has pass by sharing semantics.
Adding "with js" (equivalently javascript or javascript_semantics) to a source file effectively disables both in the desktop interpreter, and triggers appropriate run-time violations to indicate where deep_copy() is needed.
Only in that way, and with thorough testing on the desktop, can we hope to ensure the transpiler does not generate pass-by-sharing-side-effect-laden JavaScript, which would need to be debugged using the browser development tools.
Note that "with js" is ignored by the compiler, repl, and transpiler, and the latter errors out on "without js".
Aside: I don’t really expect anyone to type out "with javascript_semantics" when they can just use "with js", however searching for the latter on rosettacode is [not] going to be very productive.

The depth and bIfNeeded parameters are firmly in the premature optimisations camp and may be removed without notice.
bIfNeeded can only possibly be of any use in two cases: x = deep_copy(x) where x is a local variable, or x = deep_copy(expr) where the input argument is an unnamed temp. (The first of those may sometimes be be a completely futile operation, but sometimes the right thing to do.)
Obviously since JavaScript has no reference counts, it can do nothing but completely ignore bIfNeeded.

Has no effect if x is an atom or string, since non-1 refcounts on those do not cause JavaScript (and/or p2js.js) any trouble.

Note that deep_copy does not produce thread-safe atoms and strings, it only does that for dword-sequences and even then not any string or atom elements they may contain.
Example:
        O:={3}; P:=O;            O[1]:=5;   -- when transpiled to JavaScript: ARGH, P != {3} !!!
        O:={3}; P:=deep_copy(O); O[1]:=5;   -- when transpiled to JavaScript: ahhh, P == {3}

Of course that works as you would normally expect on desktop/Phix, with P=={3} in all cases and the caveat that the first line triggers a runtime violation on should there be a "with js" present. If you are thinking "extra typing!" when looking at that you would be correct, but if you’re also thinking "extra overhead!" then apart from the function call you’d be wrong, that kind of copy always used to have to quietly happen anyway, albeit a usually shallower copy, and fractionally later and the other way round, inside the O[1] assignment.
Implementation: See builtins\repeat.e (an autoinclude) for details of the actual implementation.
There is also a version in p2js.js which obviously uses native JavaScript functions not builtins\VM\pHeap.e\%:pAllocSeq, etc.
See Also: repeat, Incompatibilities
Expand/Shrink