Copy Semantics - r3n/rebol-wiki GitHub Wiki

This is a preliminary document to specify the semantics of COPY for A80. This also applies to MAKE object! which preforms a COPY as a default action.

Table of Contents

How values are effected by copying

When a copy of a block or object is made, the copy operation handles various datatypes differently:

  • immediate values - these are always copied (integer! decimal! logic! etc.)
  • indirect values - can be copied if so desired (string! binary! block! etc.)
  • restricted values - cannot be copied (gob!, task!, port!)
It should be noted that restricted values aren't copied because they may hold unique internal state data. For example, a gob is normally part of a linked list, and to copy those linkage pointers destroys the list's integrity.

Copy modes

There are a few useful modes of copying:

  • shallow - copy a block or object keeping all its values as non-copied references (values are shared).
  • deep - copy a block or object, then copy all its series values (values are not shared).
  • all - same as deep, but also copy all other copyable values such as bitsets, vectors, images, maps, objects, errors, etc.
  • bind - same as deep, but also copy functions and closures that will be rebound in a new environment (this is a special mode used by MAKE object!)
These modes are implemented in the COPY API with two refinements:
  • COPY/types - specify as a typeset the values to be copied. Note that you can use /types without /deep, in which case the copy is applied only to the top level of values.
  • COPY/deep - perform the copy recursively on each value. If you use /deep without /types, it is assumed that you want to copy all series values (any-string!, binary!, and any-block!) but not bitsets, images, vectors, maps, functions, or objects.

Datatype table

Here is a table of types copied by default on COPY/deep and MAKE object!:

<TR>
	<TD BGCOLOR="#99CCFF"><B>Datatype</b></td>
	<TD BGCOLOR="#99CCFF"><B>COPY and MAKE</b></td>
</tr>
<TR>
	<TD><B>strings</b></td>
	<TD>yes</td>
</tr>
<TR>
	<TD><B>binary</b></td>
	<TD>yes</td>
</tr>
<TR>
	<TD><B>bitsets</b></td>
	<TD>no</td>
</tr>
<TR>
	<TD><B>vectors</b></td>
	<TD>no</td>
</tr>
<TR>
	<TD><B>images</b></td>
	<TD>no</td>
</tr>
<TR>
	<TD><B>gobs</b></td>
	<TD>no</td>
</tr>
<TR>
	<TD><B>blocks</b></td>
	<TD>yes</td>
</tr>
<TR>
	<TD><B>parens</b></td>
	<TD>yes</td>
</tr>
<TR>
	<TD><B>paths</b></td>
	<TD>yes</td>
</tr>
<TR>
	<TD><B>maps</b></td>
	<TD>no</td>
</tr>
<TR>
	<TD><B>functions</b></td>
	<TD>make object! only</td>
</tr>
<TR>
	<TD><B>closures</b></td>
	<TD>make object! only</td>
</tr>
<TR>
	<TD><B>objects</b></td>
	<TD>no</td>
</tr>
<TR>
	<TD><B>errors</b></td>
	<TD>no</td>
</tr>
<TR>
	<TD><B>ports</b></td>
	<TD>no</td>
</tr>

Internal copy operations

Internally, there are also a few places where special copy operations occur. They are:

  • COPY - as described above
  • MAKE object! - copies with deep and bind modes.
  • BIND/copy - deep copies before rebinding
  • TAKE/deep - deep copies the result block (NOTE: this should be removed, because in general this should be done with a COPY/deep of the result!)
  • MAKE function! - deep copies when parent function is provided as the source (MAKE parent-func! [...]).
  • COPY function! - deep copies the source function
  • REFLECT function! - deep copies body and/or spec to avoid manipulation of function internals
  • evaluation of closure! - deep copies the function body to rebind variables
  • some iterators - deep copy their code blocks to allow rebinding of loop related variables. They are: REPEAT, FOR, FOREACH, REMOVE-EACH, and MAP-EACH. But note, the FORALL, FORSKIP, and FOREVER functions do not deep copy.
  • DO task! - deep copies the task body to avoid environment collisions
⚠️ **GitHub.com Fallback** ⚠️