NOT-SO-STUPID COPY TRICKS
Applying 'copy to a series returns a new series whose index is the
same as the argument's index, but whose sequence is a duplicate of
the argument's sequence. Later modifications to the sequence of
data referenced by the original argument have no effect on the
result of the 'copy. Immediately after the 'copy, the argument
and result are equal, but not the same.
Evaluating
a: "1234"
leaves
a -> {{string! 1 *}}
|
V
<<#"1" #"2" #"3" #"4">>
Then evaluating
b: copy a
leaves
a -> {{string! 1 *}}
|
V
<<#"1" #"2" #"3" #"4">>
b -> {{string! 1 *}}
|
V
<<#"1" #"2" #"3" #"4">>
The two character sequences are equal, but since they are distinct
a change to one does not affect the other, so that
append a "X"
leaves
a -> {{string! 1 *}}
|
V
<<#"1" #"2" #"3" #"4" #"X">>
b -> {{string! 1 *}}
|
V
<<#"1" #"2" #"3" #"4">>
All of these predictions are confirmed by
>> a: "1234"
== "1234"
>> b: copy a
== "1234"
>> equal? a b
== true
>> same? a b
== false
>> append a "X"
== "1234X"
>> a
== "1234X"
>> b
== "1234"
However, the subject of 'copy becomes more interesting when it is
applied to a block whose contents include series values. After
evaluating
a: [1 "st" 2 "nd"]
b: a
we have
a -> {{block! 1 *}}
^ |
/ V
b -- <<1 * 2 *>>
| |
V V
{{string! 1 *}} {{string! 1 *}}
/ |
/ |
V V
<<#"s" #"t">> <<#"n" #"d">>
In this state, evaluating
c: copy a
should duplicate the sequence referred to by a. Note that this
sequence includes both "atomic" values (1 and 2) and series values
(which refer to the two strings). Duplicating all of these (atomic
values and references, but NOT the sequences) leaves
a -> {{block! 1 *}}
^ |
/ V
b -- <<1 * 2 *>>
| |
V V
{{string! 1 *}} {{string! 1 *}}
/ ^ ^ |
/ | | |
V | | V
<<#"s" #"t">> | | <<#"n" #"d">>
| |
<<1 * 2 *>>
^
|
c -> {{block! 1 *}}
>From this diagram, it should be clear [well, about as clear as I can
manage, using ASCII art instead of nice graphics!] that modifying
the sequence referenced by a's value will have an effect seen via b,
and vice versa (because they ultimately refer to the same sequence).
However, modifications to that sequence will NOT be seen via c
(because c's series refers to a COPY of the sequence shared by a
and b). Evaluating
append b [3 "rd"]
changes the above diagram to
a -> {{block! 1 *}}
^ |
/ V
b -- <<1 * 2 * 3 *>>
| | |
| | V
| | {{string! 1 *}}
| | |
| | V
| | <<#"r" #"d">>
V V
{{string! 1 *}} {{string! 1 *}}
/ ^ ^ |
/ | | |
V | | V
<<#"s" #"t">> | | <<#"n" #"d">>
| |
<<1 * 2 *>>
^
|
c -> {{block! 1 *}}
However, modifying the strings nested in a's (or b's) value WILL
cause an effect visible via c, because the series at c/2 is the same
as the series at a/2 (similarly for c/4 and a/4). The effects of
insert a/2 a/1
insert a/4 a/3
may be diagrammed as
a -> {{block! 1 *}}
^ |
/ V
b -- <<1 * 2 * 3 *>>
| | |
| | V
| | {{string! 1 *}}
| | |
| | V
| | <<#"r" #"d">>
V V
{{string! 1 *}} {{string! 1 *}}
/ ^ ^ |
/ | | |
V | | V
<<#"s" #"t">> | | <<#"n" #"d">>
| |
<<1 * 2 *>>
^
|
c -> {{block! 1 *}}
which predicts that c's value will print as
[1 "1st" 2 "2nd"]
This prediction is correct, as shown by
>> a: [1 "st" 2 "nd"]
== [1 "st" 2 "nd"]
>> b: a
== [1 "st" 2 "nd"]
1) >> c: copy a
== [1 "st" 2 "nd"]
>> append b [3 "rd"]
== [1 "st" 2 "nd" 3 "rd"]
>> a
== [1 "st" 2 "nd" 3 "rd"]
>> b
== [1 "st" 2 "nd" 3 "rd"]
2) >> c
== [1 "st" 2 "nd"]
>> insert a/2 a/1
== "st"
>> insert a/4 a/3
== "nd"
>> a
== [1 "1st" 2 "2nd" 3 "rd"]
>> b
== [1 "1st" 2 "2nd" 3 "rd"]
3) >> c
== [1 "1st" 2 "2nd"]
To avoid this entanglement, the /deep refinement may be used. This
causes any series values nested within a series argument to be
copied. The upper-level sequence refers to the copies of the nested
values, making the deep copy independent of the original at all
levels.
Changing line 1) to read
1') >> c: copy/deep a
== [1 "st" 2 "nd"]
produces the following state of affairs
a -> {{block! 1 *}}
^ |
/ V
b -- <<1 * 2 *>>
| |
V V
{{string! 1 *}} {{string! 1 *}}
/ |
/ |
V V
<<#"s" #"t">> <<#"n" #"d">>
c -> {{block! 1 *}}
|
V
<<1 * 2 *>>
| |
V V
{{string! 1 *}} {{string! 1 *}}
/ |
/ |
V V
<<#"s" #"t">> <<#"n" #"d">>
which causes us to predict that ANY modifications made via a or b
will have no effect on anything under c. Continuing after that
(changed) line leaves the result of line 2) APPEARING the same, but
line 3) now will return a result unmodified since line 2).
3') >> c
== [1 "st" 2 "nd"]
(end of the essay)