REBOL 3 Docs Guide Concepts Functions Datatypes Errors
  TOC < Back Next >   Updated: 13-Aug-2010 Edit History  

REBOL 3 Functions: copy

copy  value  /part  length  /deep  /types  kinds

Copies a series or object.

Arguments:

value [series! port! map! object! bitset! any-function!]

Refinements:

/part - Limits to a given length or position

length [number! series! pair!]

/deep - Also copies series values within the block

/types - What datatypes to copy

kinds [typeset! datatype!]

See also:

make   form   mold   join   ajoin   rejoin  

Description

The copy function will copy any series, such as string! or block!, and most other compound datatypes such as object! or function!. It is not used for immediate datatypes, such as integer!, decimal!, time!, date!, and others.

How it Works

It is important to understand copy to program in REBOL properly.

To save memory, all strings, blocks, and other series are accessed by reference (e.g. as pointers.) If you need to modify a series, and you do not want it to change in other locations, you must use copy first.

Note that some functions, such as join and rejoin, will copy automatically. That's because they are constructing new values.

This example shows what happens if you don't copy:

name: "Tesla"
print name
Tesla
name2: name
insert name2 "Nicola "
print name2
Nicola Tesla
print name
Nicola Tesla

That's because, it's the same string:

same? name name2
true

Here's the example using copy for the second string:

name: "Tesla"
print name
Tesla
name2: copy name
insert name2 "Nicola "
print name2
Nicola Tesla
print name
Tesla
same? name name2
false

The same behavior is also true for blocks. This example shows various results:

block1: [1 2 3]
block2: block1
block3: copy block1
append block1 4
append block2 5
append block4 6
probe block1
[1 2 3 4 5]
probe block2
[1 2 3 4 5]
probe block3
[1 2 3 6]

There will be times in your code where you'll want to append to or insert in a string or other series. You will need to think about what result you desire.

Compare this example:

str1: "Nicola"
str2: append str1 " Tesla"
print str1
Nicola Tesla
print str2
Nicola Tesla

with this example that uses the copy function:

str1: "Nicola"
str2: append copy str1 " Tesla"
print str1
Nicola
print str2
Nicola Tesla

Copy Part

It is fairly common to copy just a sub-string or sub-block. To do so, use the /part refinement. The length of the result is determined by an integer size or by the ending position location.

name: "Nicola Tesla"
copy/part name 6
"Nicola"
copy/part skip name 7 5
"Tesla"
copy/part find name "Tesla" tail name
"Tesla"

Notice that the ending position can be a length or a position within the string (as shown by the tail example above.)

About Substrings

If you use other languages, you will notice that this result is similar to what a substr function provides. Although we recommend using copy with /part, you can easily define your own substr function this way:

substr: func [arg [series!] start length] [
    copy/part skip arg start length
]

For example:

substr "string example" 7 7
"example"

We should explain why we don't normally define a substr function. Most of the time when you're extracting substrings, you are either using a function like find or you're using a loop of some kind. Therefore, you don't really care about the starting offset of a string, you only care about the current location.

For example:

str: "This is an example string."
str2: copy/part find str "ex" 7

And, in fact, it's common to write use two find functions in this way:

start: find str "ex"
end: find start "le"
str2: copy/part start end

which advanced users often write in one line this way:

str2: copy/part s: find str "ex" find s "le"

Of course, if the string might not be found, this is a helpful pattern to use:

str2: all [
    start: find str "ex"
    end: find start "le"
    copy/part start end
]

If the start or end are not found, then str2 is set to none.

Here's an example of a simple loop that finds substrings:

str: "this example is an example"
pat: "example"
while [str: find str pat] [
    print copy/part str length? pat
    str: skip str length? pat
]

Copy Deep

When copying blocks, keep in mind that simple use of the copy function does not make copies of series values within a block.

Notice that the copy here does not copy the name string:

person1: ["Tesla" 10-July-1856 Serbian]
person2: copy person1
insert person/2 "Nicola "
probe person1
["Nicola Tesla" 10-July-1856 Serbian]

If you need to copy both the block and all series values within it, use copy with the /deep refinement:

person1: ["Tesla" 10-July-1856 Serbian]
person2: copy/deep person1
insert person/2 "Nicola "
probe person1
["Tesla" 10-July-1856 Serbian]
probe person2
["Nicola Tesla" 10-July-1856 Serbian]

Here both the block and the string are separate series.

Also be aware that if your block contains other blocks, they will be deep copied as well, including all strings and other series within them.

If you want to deep copy only a specific datatype, such as just strings or just blocks, you can use the /types refinement.

Here are a few examples of its usage:

copy/deep/types block string!
copy/deep/types block any-string!
copy/deep/types block make typeset! [string! url! file!]

Copy Objects

If you use copy on an object, a copy of the object is returned. This can be useful when objects are used only as simple storage structures. Note that rebinding is not done; therefore, do not use copy on objects when that is required.

Helpful Hint

To see a list of functions that modify their series (not copy), type this line:

? modifies
Found these related words:
alter           function! If a value is not found in a series, append i...
append          action!   Inserts a value at tail of series and returns...
bind            native!   Binds words to the specified context. (Modifi...
change          action!   Changes a value in a series and returns the s...
clear           action!   Removes all values. For series, removes from ...
decloak         native!   Decodes a binary string scrambled previously ...
deline          native!   Converts string terminators to standard forma...
detab           native!   Converts tabs in a string to spaces (default ...
encloak         native!   Scrambles a binary string based on a key. (Mo...
enline          native!   Converts standard string terminators to curre...
entab           native!   Converts spaces in a string to tabs (default ...
insert          action!   Inserts into a series and returns the series ...
lowercase       native!   Converts string of characters to lowercase. (...
...


  TOC < Back Next > REBOL.com - WIP Wiki Feedback Admin