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

REBOL 3 Concepts: Expressions: Conditionals

Pending Revision

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

As previously mentioned, blocks are not normally evaluated. A do function is required to force a block to be evaluated. There are times when you may need to conditionally evaluate a block. The following section describes several ways to do this.


Conditional Blocks

The if function takes two arguments. The first argument is a condition and the second argument is a block. If the condition is true , the block is evaluated, otherwise it is not evaluated.

if now/time > 12:00 [print "past noon"]
past noon

The condition is normally an expression that evaluates to true or false ; however, other values can also be supplied. Only a false or a none! value prevents the block from being evaluated. All other values (including zero) are treated as true, and cause the block to be evaluated. This can be useful for checking the results of find, select, next, and other functions that return none! :

string: "let's talk about REBOL"
if find string "talk" [print "found"]

The either function extends if to include a third argument, which is the block to evaluate if the condition is false:

either now/time > 12:00 [
    print "after lunch"
    print "before lunch"
after lunch

The either function also interprets a none! value as false.

Both the if and either functions return the result of evaluating their blocks. In the case of an if, the block value is only returned if the block is evaluated; otherwise, a none! is returned. The if function is useful for conditional initialization of variables:

flag: if time > 13:00 ["lunch eaten"]

print flag
lunch eaten

Making use of the result of the either function, the previous example could be rewritten as follows:

print either now/time > 12:00 [
    "after lunch"
    "before lunch"
after lunch

Since both if and either are functions, their block arguments can be any expression that results in a block when evaluated. In the following examples, words are used to represent the block argument for if and either.

notice: [print "Wake up!"]
if now/time > 7:00 notice
Wake up!
notices: [
    [print "It's past sunrise!"]
    [print "It's past noon!"]
    [print "It's past sunset!"]
if now/time > 12:00 second notices
It's past noon!
sleep: [print "Keep sleeping"]
either now/time > 7:00 notice sleep
Wake up!

The conditional expressions used for the first argument of both if and either can be composed from a wide variety of comparison and logic functions. Refer to the math Chapter for more information.

Avoid This Common Mistake

The most commonly made mistake in REBOL is to forget the second block on either or add a second block to if. These examples both creator hard-to-find errors:

either age > 10 [print "Older"]

if age > 10 [print "Older"] [print "Younger"]

These types of errors may be difficult to detect, so keep this in mind if these functions do not seem to be doing what you expect.

Any and All

The any and all functions offer a shortcut to evaluating some types of conditional expressions. These functions can be used in a number of ways:either in conjunction with if, either, and other conditional functions, or separately.

Both any and all accept a block of expressions, which is evaluated one expression at a time. The any function returns on the first true expression, and the all function returns on the first false expression. Keep in mind that a false expression can also be none!, and that a true expression is any value other than false or none!.

The any function returns the first value that is not false, otherwise it returns none!. The all function returns the last value if all the expressions are not false, otherwise it returns' none!.

Both the any and all functions only evaluate as much as they need. For example, once any has found a true expression, none of the remaining expressions are evaluated. Here is an example of using any :

size: 50
if any [size < 10 size > 90] [
    print "Size is out of range."

The behavior of any is also useful for setting default values. For example, the following lines set a number to 100, but only when its value is none! :

number: none
print number: any [number 100]

Similarly, if you have various potential values, you can use the first one that actually has a value (is not none! ):

num1: num2: none
num3: 80
print number: any [num1 num2 num3]

You can use any with functions like find to always return a valid result:

data: [123 456 789]
print any [find data 432 999]

Similarly, all can be used for conditions that require all expressions to be true :

if all [size > 10 size < 90] [print "Size is in range"]
Size is in range

You can verify that values have been set up before evaluating a function:

a: "REBOL/"
b: none
probe all [string? a string? b append a b]
b: "Core"
probe all [string? a string? b append a b]

Conditional Loops

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

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

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

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.

  TOC < Back Next > - WIP Wiki Feedback Admin