TOC < Back Next > Updated: 15-Feb-2009 Edit History

# REBOL 3 Concepts: Series: Traversing

Pending Revision

This document was written for R2 and has yet to be revised for R3.

## Traversing a Series

Since a series is an ordered set of values, you can traverse it from one position to another. As an example, take a series of three colors defined by the following block:

`colors: [red green blue]`

There is nothing special about this block. It is a series containing three words. It has a set of values: red, green, and blue. The values are organized into a specific order: red is first, green is second, and blue is third.

The first position of the block is called its head. This is the position occupied by the word red. The last position of the block is called its tail. This is the position immediately after the last word in the block. If you were to draw a diagram of the block, it would look like this:

Notice that the tail is just past the end of the block. The importance of this will become more clear shortly.

The variable colors is used to refer to the block. It is currently set to the head of the block:

```print head? colors
true```

The colors variable is at the first index position of the block.

```print index? colors
1```

The block has a length of three:

```print length? colors
3```

The first item in the block is:

```print first colors
red```

The second item in the block is:

```print second colors
green```

You can reposition the colors variable in the block using various functions. To move the colors variable to the next position in the colors block, use the next function:

`colors: next colors`

The next function moves forward one value in the block and returns that position as a result. The colors variable is now set to that new position:

The position of the colors variable has changed. Now the variable is no longer at the head of the block:

```print head? colors
false```

It is at the second position in the block:

```print index? colors
2```

However, if you obtain the first item of colors, you get:

```print first colors
green```

The position of the value that is returned by the first function is relative to the position that colors has in the block. The returned value is not the first color in the block, but the first color immediately following the current position of the block.

Similarly, if you ask for the length or the second color, you find that these are relative as well:

```print length? Colors
2```
```print second colors
blue```

You could move to the next position, and get a similar set of results:

```colors: next colors

print index? colors
3```
```print first colors
blue```
```print length? colors
1```

The block diagram now looks like this:

The colors variable is now at the last color in the block, but it is not yet to the tail position.

```print tail? colors
false```

To reach the tail, it has to be moved to the next position:

`colors: next colors`

Now the colors variable is resting at the tail of the block. It is no longer positioned at a valid color. It is past the end of the block.

If you try your code, you will get:

```print tail? colors
true```
```print index? colors
4```
```print length? Colors
0```
```print first colors
** Script Error: Out of range or past end.
** Where: print first colors```

You receive an error in this last case because there is no valid first item when you are past the end of the block.

It is also possible to move backwards in the block. If you write:

`colors: back colors`

you will move the colors variable back one position in the series:

All of the same code will work as before:

```print index? colors
3```
```print first colors
blue```

## Skipping Around

The previous examples move through the series one item at a time. However, there are times when you want to skip past multiple items using the skip function. Assume that the colors variable is positioned at the head of a series:

You can skip forward two items using:

`colors: skip colors 2`

The skip function is similar to next in that skip returns the series at the new position.

The following code confirms the new position:

```print index? colors
3```
```print first colors
blue```

To move backward, use skip with negative values:

`colors: skip colors -1`

This is similar to back. In the above example, a skip of -1 moves back one item.

```print first colors
green```

Note that you cannot skip past the tail or the head of a series. If you attempt to do so, skip only goes as far as it can. It will not generate an error.

If you skip too far forward, skip returns the tail of the series:

```colors: skip colors 20

print tail? colors
true```

```colors: skip colors -100

true```

To skip directly to the head of the series, use the head function:

```colors: head colors

true```
```print first colors
red```

```colors: tail colors

print tail? colors
true```

## Extracting Values

Some of the previous examples made use of the first and second ordinal functions to extract specific values from a series. The full set of ordinal functions is:

```first
second
third
fourth
fifth
last```

Ordinal functions are provided as a convenience, and are used for picking values from the most common position in a series. Here are some examples:

```colors: [red green blue gold indigo teal]

print first colors
red```
```print third colors
blue```
```print fifth colors
indigo```
```print last colors
teal```

To extract from a numeric position, use the pick function:

```print pick colors 3
blue```
```print pick colors 5
indigo```

A shorthand notation for pick is to use a path:

```print colors/3
blue```
```print colors/5
indigo```

Remember, as shown earlier, extraction is performed relative to the series variable that you provide. If the colors variable were at another position in the series, the results would be different.

Extracting a value past the end of its series generates an error in the case of the ordinal functions and returns none! in the case of the pick function or a pick path:

```print pick colors 10
none```
```print colors/10
none```

## Extracting a Sub-series

You can extract multiple values from a series with the copy function. To do so, use copy with the /part refinement, which specifies the number of values that you want to extract:

```colors: [red green blue]

sub-colors: copy/part colors 2

probe sub-colors
[red green]```

Graphically, this would look like:

To copy a sub-series from any position within the series, first traverse to the starting position. The following example moves forward to the second position in the series using next before performing the copy:

```sub-colors: copy/part next colors 2

probe sub-colors
[green blue]```

This would be diagrammed as:

The length of the series to copy can be specified as an ending position, as well as a copy count. Note that the position indicates where the copy should stop, not the ending position.

```probe copy/part colors next colors
[red]```
```probe copy/part colors back tail colors
[red green]```
```probe copy/part next colors back tail colors
[green]```

This can be useful when the ending position is found as the result of the find function:

```file: %image.jpg

print copy/part file find file "."
image```

## Inserting and Appending

You can insert one or more new values into any part of a series using the insert function. When you insert a value at a position in a series, space is made by shifting its prior values toward the tail of the series.

For instance, the block:

`colors: [red green]`

would be shown as:

To insert a new value at the head of the block where the colors variable is now positioned:

`insert colors 'blue`

The red and green words are shifted over and the blue word (which is prefixed with a tick because it is a word and should not be evaluated) is inserted at the head of the list.

Note that the colors variable remains positioned at the head of the list.

```probe colors
[blue red green]```

Also note that the return from the insert function was not used because it was not set to a variable or passed along to another function. If the return had been used to set the value of the colors variable with the line:

`colors: insert colors 'blue`

the effect on the block would have been the same, but the position of the colors variable would have changed as a result of setting the return value. The position returned from insert is immediately following the insertion point.

An insertion can be made anywhere in the series. The position of the insert can be specified, and it can include the tail. Inserting at the tail has the effect of appending to the series.

```colors: tail colors

insert colors 'gold

probe colors
[blue red green gold]```

Before the insertion:

After the insertion:

The word gold has been inserted at the tail of the series.

Another way to insert at the tail of a series is with the append function. The append function works in the same way as insert, but always inserts at the tail. The previous example would become:

`append colors 'gold`

The result is the same as the previous example.

The insert and append function also accept a block of arguments to insert. As an example:

```colors: [red green]

insert colors [blue yellow orange]

probe colors
[blue yellow orange red green]```

If you want to insert the new values between the red and green words:

```colors: [red green]

insert next colors [blue yellow orange]

probe colors
[red blue yellow orange green]```

The insert and append functions have other capabilities that are covered in more detail in a later section.

## Removing Values

You can remove one or more values from any part of a series by using the remove function.

For instance, starting with the block:

`colors: [red green blue gold]`

As shown here:

You can remove the first value from the block with the line:

`remove colors`

The block becomes:

It can be printed with:

```probe colors
[green blue gold]```

The remove function removes values relative to the position of the colors variable. You can remove values from anywhere in the series by setting the position.

`remove next colors`

The block is now:

Multiple values can be removed by supplying the /part refinement.

`remove/part colors 2`

This removes the remaining values, leaving an empty block:

Similar to insert/part, the argument to remove/part can also be a position within the block.

Removing all of the remaining values is a common operation. The clear function is provided to make this more direct. clear removes all values from the current position to the tail. For example:

`Colors: [blue red green gold]`

As shown here:

Everything after blue can be removed with:

`clear next colors`

The block becomes:

You can easily clear the entire block with:

`clear colors`

## Changing Values

One additional set of functions is provided for changing values in a series. The change function replaces one or more values with new values. Although this can be accomplished by removing and inserting values, it is more efficient to use change.

Defining the block:

`colors: [blue red green gold]`

Its second value could be changed with the line:

`change next colors 'yellow`

And it would become:

The block would now become:

```probe colors
[blue yellow green gold]```

The poke function allows you to specify that the change occur at a particular position relative to the colors variable. The poke function is similar to the pick function described earlier.

`poke colors 3 'red`

The block is now:

As proven by:

```probe colors
[blue yellow red gold]```

The change function has additional refinements that are described later in this chapter.

 TOC < Back Next > Feedback Admin