|REBOL 3 Docs||Guide||Concepts||Functions||Datatypes||Errors|
|TOC < Back Next >||Updated: 12-Apr-2009 Edit History|
This section describes conditional evaluation.
Be sure you know the basics of evaluation from the prior section: code: how code is evaluated.
A conditional expression is one that evaluates to true or false.
10 > 4 true
empty? "" true
empty? "test" false
However, in REBOL we allow a true condition to be more than just the value true - almost any other value is accepted as a true value. This allows us to simplify many expressions, but at the slight cost that you must keep the rule in mind.
Here is the rule: any value that is not false and not none is true.
So, these are all considered true:
true "bob" 0 123 12:30 [a b c] %file
and, other such values.
The if function evaluates an expression, and if it is true, evaluates the block that follows.
n: 14 if n > 10 [print "greater than 10"] greater than 10
Any expression that returns false or none will not evaluate the block. All others will. Therefore, you can use expressions that return other values. Here's a common one:
string: "let's talk about REBOL" if find string "talk" [print "found"] found
Because if is a function it returns a value. For a true condition it returns the result of the block evaluation, or none when false:
n: 10 print if n > 3 ["greater"] greater
n: 1 print if n > 3 ["greater"] none
Also, notice that you can pass variables for block arguments:
then-block: [print "greater than 10"] n: 14 if n > 10 then-block greater than 10
In fact the block also be the result of some other expression, that returns a block. More on that later.
The either function is used to evaluate one of two blocks. It's what you use for an if-else type of expression. (REBOL does not use else.)
The either function takes one condition and two blocks:
n: 10 print either n > 20 ["greater"] ["not greater"] not greater
Any condition that is false or none will evaluate the second block.
print either n > 20 ["greater"] ["not greater"] not greater
Also, the block values can be variables, defined earlier or even returned as results from other functions:
then-block: [n - 2] else-block: [n + 2] n: 10 print either n > 20 then-block else-block 12
These are both wrong, but they may or may not cause a run-time error:
if n > 50 [print "greater"] [print "not greater"] ; extra block! either age > 50 [print "greater"] ; missing a block!
The any function will evaluate a block of expressions until one is true (is not [bad-link:functions/false.txt] or [bad-link:functions/none.txt]). The all function requires that all the expressions are true.
An example of any is:
n: -10 if any [n < 0 n > 100] [print "out of range"] out of range
And all is:
n: 10 if all [n > 0 n < 100] [print "in range"] in range
Here is a very common programming pattern:
name: "Bob" if all [ string? name not empty? name find ["Bob" "Ned" "Sam"] name ][ print "found name" ] found name
name: "Sam" print all [ string? name spot: find ["Bob" "Ned" "Sam"] name index? spot ] 3
See expressions: conditionals for more details.
In many languages, it is common to stack if and else statements in a pattern like:
if ... else if ... else if ... else ...
It has the general form:
case [ condition1 [expression1] condition2 [expression2] ... ]
n: 10 case [ n > 100 [print "too large"] n > 20 [print "still too large"] n < 0 [print "too small"] true [print "in range"] ] in range
Note the use of true for the last case, evaluated when all the others fail.
And, because case is a function that returns a result, the above example could be written:
n: 10 print case [ n > 100 ["too large"] n > 20 ["still too large"] n < 0 ["too small"] true ["in range"] ] in range
It turns out that case does not require blocks for simple values, so you can further reduce this down to:
n: 10 print case [ n > 100 "too large" n > 20 "still too large" n < 0 "too small" true "in range" ] in range
The case function also has a refinement that lets you evaluate all the conditional expressions. See the function description for more detail.
The switch function finds a matching value and evaluates its related block.
The matched value can be of any datatype. Simple integers for example:
n: 22 switch n [ 11 [print "here"] 22 [print "there"] 33 [print "everywhere"] ] there
You can also tell switch to evaluate a default block, if no values are matched:
n: 123 switch/default n [ 11 [print "here"] 22 [print "there"] 33 [print "everywhere"] ][ print "nowhere" ] nowhere
There are many uses for switch as shown here:
name: "Sam" switch n [ "Bob" [print "here"] "Sam" [print "there"] "Ted" [print "everywhere"] ] there
html-tag: <title> print switch html-tag [ <pre> ["preformatted text"] <title> ["page title"] <li> ["bulleted list item"] ] page title
time: 12:30 switch time [ 8:00 [send firstname.lastname@example.org "Hey, get up"] 12:30 [send email@example.com "Join me for lunch."] 16:00 [send firstname.lastname@example.org "Dinner anyone?"] ]
Note that the switch block is not evaluated so if it contains expressions, you will need to use reduce first:
n: 22 switch n reduce [ 11 [print "here"] 11 * 2 [print "there"] 11 * 3 [print "everywhere"] ] there
If you want to use switch on datatypes, use this method:
n: 22 switch type?/word n [ integer! [print "integer"] decimal! [print "decimal"] time! [print "time" ]
See the type? function for details.
Also, like other functions, switch returns the value of the block it has evaluated.
|TOC < Back Next >||REBOL.com - WIP Wiki||Feedback Admin|