# Rebol Programming/Language Features/Control

REBOL offers a variety of different control structures with many similar to those seen in other computer languages, and some unique to itself.

## Logic Functions
### All

all is a useful function that allows one to check to see if all the expressions in a block evaluate to true or not. It obviates the need for cascading the either constructs.
Now, the useful thing is that although we can use it to test for multiple conditions as above, we can perform multiple tasks inside the block as long as each expression returns a value distinct from false or none.
Interestingly, the all construct ensures that all of the preceding expressions must be true before we complete our list of tasks, and spam-our-customers. We wouldn't want to do this if the update to our website had not completed!
The above example takes advantage of an important property of all which is that it does not evaluate further when it encounters false or none. This way the preceding conditions can "guard" the subsequent ones, like e.g.:
The same would not be true when using the and operator:
NB: Although the help for all says that it is shortcut for and, it is not really. So, note the following
where the return value is none and not a logic! false.

### Any

any returns true if any of the expressions inside the block returns true.
Similarly as with all, any "guards" the subsequent conditions, if it encounters a value considered true (i.e. anything distinct from false and none). Again, this property does not hold for the or operator.

## Conditionals
### If, Either and Unless

The if function allows one to conditionally evaluate a block if the condition argument is true (which means, distinct from false or none). Otherwise if returns none. If the /else refinement is used, then the second block is evaluated in case the condition is false.
While condition can be the result of a simple expression such as
Warning: the /else refinement may not be supported in the future versions of Rebol, being considered obsolete! It is faster and future-proof to use the either native instead.
The condition can be a result of any legal function that returns a value. So, if you had a function named web-update? that checks to see if a particular page has been updated in the last few days, you could write
The either native function is conditionally evaluates its second argument (the true-block), if the first argument (the condition) is true (i.e. distinct from false and none), otherwise it evaluates its third argument (the false-block).
Truth in Rebol is somewhat different from the English language use of the same term. Anything that is not false or none is treated as true. This means that all integers, including 0, are treated as true as well as all blocks, etc.
Beginner gotcha: you should especially take care of:
, because the block is treated as true. The same holds for 0:
In place of the if not combination, we can use the unless function. Example:

### Case

The general case expression form can be:
Conditions are evaluated and checked one after another. If true, the block following the condition is evaluated and returned as the case result.
Case enhances readability replacing nested either. Example:
The example above would have been almost unreadable when written using either. Notice the true condition intended to yield "Hello dear" if none of the previous conditions was true.

### Switch

switch is similar to the case function. However, it takes a single value, and then compares that to a block of value block pairs. If the value matches, it evaluates the block, and returns its value leaving the function at that point. If there is no match, it returns none. If the default refinement is specified, then the optional last block is evaluated.
Let us say that we wish to implement a POP3 server. We know that the POP3 server is state driven, and has 2 states, an authorisation state, and a transaction state. In each of these states, the POP3 server will only accept certain commands.
The authorisation switch might look like this, where the words in the blocks are pseudocode.
In both of the above examples we have used word values for the switch, but any Rebol value can be used.

## Repetition
### For

for is much like the traditional for loop structure seen in other languages with a small twist - the increment, or bump amount, can be in a datatype other than integer! as is usually required.
So, if you wish to write a loop where the counter value is incremented in a money! type, we can do this:
giving
In case the repeat control function is suitable for the job, prefer repeat, it is faster.

### Forall

The most used loop in Rebol is foreach. But with foreach we can not change the current value as it does not give us the series-position. forall was created for that case as it gives us the position instead of the current value.
As the series is traversed, the current value becomes the first element of the series.
We can change the first element like this:
In the example above, all members of my-series are squared.
Another way to access the series is with path-notation, like my-series/1 . Then it looks
which is sometimes more comfortable.
The other advantage that forall gives you over foreach is that you have access to the index of the current element within the series being traversed.
Note that 'my-series is altered in the loop. Under certain circumstances that change stays even if the loop terminated. That happens on a break, or on an error, and is intentional.
In pre view1.3/core 2.6 releases of Rebol, the series stayed at the tail on completion of the loop which was a source of confusion for many.
Thats why you find
in some older code.

### Forskip

forskip is similar to forall in that it traverses a series while making the current element the first element of the series. It is different in that forskip allows you to move through the series by a specified integer amount. From 1.3, it also reset the series on completion. The same advantages forall has over foreach apply to forskip. Example:
produces the following output
Say we now wanted to add 1000 to the area code. Here's one way of doing that using forskip
giving
And here's an alternate way of doing this using the path notation which removes the necessity to reverse the series:

### Foreach

foreach is arguably the most common repetition structure used in Rebol. Like the majority of repetition structures, it does not affect the series it traverses.
In this example, the current directory is read and stored as a series in the word files. In the foreach structure, the temporary variable file is assigned the value of the current element in the series, and then printed to the console. The temporary variable file is local only to the evaluation block.
This can also be written as
doing away with the necessity to define the word files. If you really do want the word files, you can also do this
saving one line in your source code.
If your series comes in pairs, you can create a pair of temporary variables
which prints the first name, a space, the surname, and then starts a newline.

### Forever

Forever evaluates a block endlessly unless terminated at the console with the ESCAPE key, or a function inside the block.
What is it used for? Well, it could be used to increase one's Karmic credits! In Tibet mechanical prayer wheels are used to spin prayers such as "Om Mani Padme Hum". His Holiness the Dalai Lama has stated that computers can be used for the same effect (since the hard drive is also spinning).
So, here we have a Rebol prayer wheel in action
However, a more common usage of forever is to set up a server loop

### Loop

loop allows you to evaluate a block a specified number of times unless exited inside the block. However, there is no local counter accessible, so if you wish to track at which repetition, you will have to create your own variable for this. Alternatively you could use the for function.
loop returns the value of the last execution of the block, and is here assigned to result. If we had used print instead, we would have had an error as print does not return a value.

### Repeat

repeat evaluates a block, and has a local counter available. If the repetition value is an integer, then the counter starts at one, and reaches the repetition value.
If it is a series, then the "counter" takes the value in the series
The final value is returned.

### Until

Until is a control flow function checking the condition at the end of evaluation of its block argument.
until evaluates a block repeatedly until the block evaluates to true.
Here we prompt the user to input a password. If it matches the secret value, a true value is obtained, and we exit the block. We ensure that the test is case sensitive by using == rather than the case insensitive =.

### While

while differs from until in that the body-block may not be evaluated, whereas in until the body block is always evaluated at least once.
While also differs from similar control flow constructs in other programming languages by actually evaluating the condition "anywhere" in the repetition. It can generally be used as follows:
, where neither the pre-check stuff, nor the post-check stuff are necessary.
This example is equivalent to forever
, and it is a case when the condition is evaluated "at the start of a repetition", since no evaluation precedes the true expression in the cond-block.
Another example how to write an infinite loop using while:
, in this case the condition is actually evaluated "at the end of a repetition", since nothing is done after the cond-block (yielding the true value) is evaluated and before another repetition starts.
It is quite common to use while to skip through a series

### Break

There is a couple of methods that can be used to stop the repetition of any repetitive control function. Specifically we can use the break function. Compare the following code with the general example used in the while section:
The break function has got a /return refinement enabling us to cause the repetitive control function to return a specific value.
There are two other methods which can be used to stop the repetition. We can use the return or exit function if the repetition is done in a function or the throw function, if the repetition is done in a catch block.