REBOL 3 Docs Guide Concepts Functions Datatypes Errors
  TOC < Back Next >   Updated: 18-Apr-2009 Edit History  

REBOL 3 Guide: Code: Repeated evaluation (loops)

The purpose of this section is to provide a summary of how loops are created.

Contents

Loop

The loop function is the simplest way to evaluate a block a given number of times.

loop 3 [print "Hello world"]
Hello world
Hello world
Hello world

The loop function returns the value of the final evaluation of the block:

i: 0
print loop 40 [i: i + 10]
400

Repeat

The repeat function extends loop by allowing you to refer to the loop counter variable.

The repeat function's first argument is a word that will be used to hold the count value:

repeat count 3 [print ["count:" count]]
count: 1
count: 2
count: 3

Notice that repeat is one-based. The counter begins at one, not zero.

The final block value is also returned:

i: 0
print repeat count 10 [i: i + count]
55
Important to know:

In the above loop, and many that follow, the count word only has its counting value within the block.

We say that count is local to the block. (A special context exists while the block is evaluated. See bind for details.)

Any value that count had before the loop, it will still have after the loop. The loop does not effect it.

For example:

count: "test"

repeat count 3 [print ["count:" count]]
count: 1
count: 2
count: 3
print count
test

For

The for function is rarely used in REBOL code, because other types of loops are easier to write. However, for basically extends repeat by allowing a starting value, the ending value, and specification of the increment amount.

The example below begins at zero and counts to 50, incrementing by 10 each time through the loop:

for count 0 50 10 [print count]
0
10
20
30
40
50

Notice that the for function iterates the loop up to and including the ending value. However, if the count exceeds the ending value, the loop is terminated. The example below specifies an ending value of 55. That value will never be hit because the loop increments by 10 each time. The loop stops at 50.

for count 0 55 10 [prin [count " "]]
0 10 20 30 40 50

The next example shows how to count down. It begins at four and counts down to zero one at a time.

for count 4 0 -1 [print count]
4
3
2
1
0

The for function also works for decimal numbers, money, times, dates, series, and characters. Be sure that both the starting and ending values are of the same datatype. Here are several examples of using the for loop with other datatypes.

for count 10.5 0.0 -1 [prin [count " "]]
10.5 9.5 8.5 7.5 6.5 5.5 4.5 3.5 2.5 1.5 0.5
for money $0.00 $1.00 $0.25 [prin [money " "]]
$0.00 $0.25 $0.50 $0.75 $1.00
for time 10:00 12:00 0:20 [prin [time " "]]
10:00 10:20 10:40 11:00 11:20 11:40 12:00
for date 1-jan-2000 4-jan-2000 1 [prin [date " "]]
1-Jan-2000 2-Jan-2000 3-Jan-2000 4-Jan-2000
for char #"a" #"z" 1 [prin char]
abcdefghijklmnopqrstuvwxyz

The for function also works on series. The following example uses for on a string value. The word end is defined as the string with its current index at the d character. The for function moves through the string series one character at a time and stops when it reaches the character position defined to end:

str: "abcdef"
end: find str "d"
for s str end 1 [print s]
abcdef
bcdef
cdef
def

Foreach

The foreach function provides a convenient way to repeat the evaluation of a block for each element of a series. It works for all types of block and string series.

In the example below, each word in the block will be printed:

colors: [red green blue]
foreach color colors [print color]
red
green
blue

In the next example, each character in a string will be printed:

string: "REBOL"
foreach char string [print char]
R
E
B
O
L

In the example below, each filename in a directory block will be printed:

files: read %.
foreach file files [
    if find file ".t" [print file]
]
file.txt
file2.txt
newfile.txt
output.txt

When a block contains groups of values that are related, the foreach function can fetch all the values of the group at the same time. For example, here is a block that contains a time, string, and price. By providing the foreach function with a block of words for the group, each of their values can be fetched and printed.

movies: [
     8:30 "Contact"      $4.95
    10:15 "Ghostbusters" $3.25
    12:45 "Matrix"       $4.25
]

foreach [time title price] movies [
    print ["watch" title "at" time "for" price]
]
watch Contact at 8:30 for $4.95
watch Ghostbusters at 10:15 for $3.25
watch Matrix at 12:45 for $4.25

In the above example, the foreach value block, [''time title price], specifies that three values are to be fetched from movies for each evaluation of the block.

The variables used to hold the foreach values are local to the block. Their value are only set within the block that is being repeated. Once the loop has exited, the variables return to their previously set values.

Forall and Forskip

Similar to foreach, the forall function evaluates a block for every value in a series. However, there are some important differences. The forall function is handed the series that is set to the beginning of the loop. As it proceeds through the loop, forall modifies the position within the series.

colors: [red green blue]
forall colors [print first colors]
red
green
blue

In the above example, after each evaluation of the block, the series is advanced to its next position. When forall returns, the color index is at the tail of the series.

To continue to use the series you will need to return it to its head position with the following line:

colors: head colors

The forskip function evaluates a block for groups of values in a series. The second argument to forskip is the count of how many elements to move forward after each cycle of the loop.

Like forall, forskip is handed the series with the series index set to where it is to begin. Then, forskip modifies the index position as it continues the loop. After each evaluation of the body block, the series index is advanced by the skip amount to its next index position. The following example demonstrates forskip :

movies: [
     8:30 "Contact"      $4.95
    10:15 "Ghostbusters" $3.25
    12:45 "Matrix"       $4.25
]

forskip movies 3 [print second movies]
Contact
Ghostbusters
Matrix

In the above example, forskip returns with the movies series at its tail position. You will need to use the head function to return the series back to its head position.

Forever

The forever function evaluates a block endlessly or until a it encounters the break function.

The following example uses forever to check for the existence of a file every ten minutes:

forever [
    if exists? %datafile [break]
    wait 0:10
]

While and until

The until and while functions repeat the evaluation of a block until a condition is met.

The until function repeats a block until the evaluation of the block returns true (that is, not false or none! ). The evaluation block is always evaluated at least once. The until function returns the value of its block.

The example below will print each word in the color block. The block begins by printing the first word of the block. It then moves to the next color for each color in the block. The tail? function checks for the end of the block, and will return true, which will cause the until function to exit.

color: [red green blue]
until [
    print first color
    tail? color: next color
]
red
green
blue

The break function can be used to escape from the until loop at any time.

The while function repeats the evaluation of its two block arguments while the first block returns true. The first block is the condition block, the second block is the evaluation block. When the condition block returns false or none!, the expression block will no longer be evaluated and the loop terminates.

Here is a similar example to that show above. The while loop will continue to print a color while there are still colors to print.

color: [red green blue]
while [not tail? color] [
    print first color
    color: next color
]
red
green
blue

The condition block can contain any number of expressions, so long as the last expression returns the condition. To illustrate this, the next example adds a print to the condition block. This will print the index value of the color. It will then check for the tail of the color block, which is the condition used for the loop.

color: [red green blue]
while [
    print index? color
    not tail? color
][
    print first color
    color: next color
]
1
red
2
green
3
blue
4

The last value of the block is returned from the while function.

A break can be used to escape from the loop at any time.

Break

You can stop the repeated evaluation of a block with the break function. The break function is useful when a special condition is encountered and the loop must be stopped. The break function works with all types of loops.

In the following example, the loop will break if a number is greater than 5.

repeat count 10 [
    if (random count) > 5 [break]
    print "testing"
]
testing
testing
testing

The break function does not return a value from the loop unless a /return refinement is used:

print repeat count 10 [
    if (random count) > 5 [break/return "stop here"]
    print "testing"
    "normal exit"
]
testing
testing
testing
stop here

In the above example, if the repeat terminates without the condition occurring, the block returns the string normal exit. Otherwise, break/return will return the string stop here.

Continue

The continue function will cause a loop to jump back to the top.

Editor note: This section is new or has has recently changed and is still under construction.


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