A Concise Guide to Rebol
Fall 2010, David Matuszek

Background

Rebol, created by Carl Sassenrath, is free for individual use, but is not open source. Payment must be made for the use of Rebol in a commercial product, or for certain additional dialects, including one that supports sound. Rebol/Core is the "core" dialect, while Rebol/View includes the core and supports GUI programming.

Installing and Running

REBOL/View can be downloaded from http://www.rebol.com/download-view.html. Installation is very easy.

REBOL starts in a "desktop" GUI. You can click on Console to open the console window. From the console, you can enter desktop to return to the GUI.

From the GUI you can run many sample programs. Left-click on a program's icon to run it, or right-click to view and edit source code. However, this isn't well maintained, and many files are missing, but there are still a lot that are present.

The console is a REPL (Read-Eval-Print-Loop), in which you can try out things.

Fundamental Concepts

Rebol has a very simple syntax. There are only three kinds of "things":

Any text between a semicolon and the end of the line is considered to be a comment.

Whitespace is necessary to separate words from “operators” (which are also words). That is, a+b-c is a single word, not the expression a + b - c.

Evaluation is done left to right, even in arithmetic expressions; hence, 2 + 5 * 10 is 70, not 52. Parentheses may be used to control the order of operation. When a function word is evaluated, the number of arguments is determined, and that number of following things are passed in to the function.

To evaluate a function, determine the number of arguments it requires, evaluate that many arguments, and call the function with those arguments. Then proceed to the next function. For example sum: add 3 5 print sum is equivalent to (sum: (add 3 5)) (print sum).

A Rebol program stored on a file must begin with REBOL []. Various attributes can be placed within the block, such as Author: Dave. The usual extension for a Rebol file is .r.

Values

There are 45 kinds of values. Some of the most common are:

  • Numbers: 5, 3.14, 1.2E7
  • Booleans: true, false
  • Hex: #{FF00FF}
  • Strings: "Hello world"
  • Characters: #"a"
  • Functions: func [x] [2 * x]
  • Money: $4.99, EUR$4.99
  • URLs: http://google.com
  • Email: steve@apple.com
  • Files: %letter.txt
  • Dates: 8-Dec-2010
  • Times: 10:30AM
  • tags: <head>, </head>
  • Tuples: 127.0.0.1
  • Pairs: 1024x768
  • Issues: #1-800-555-1212
  • Blocks: [red green blue]

Conversion functions are to-type, e.g. to-char, to-hex, to-image, etc.

Words

There are five ways to use words:

Blocks

A block is a sequence of items inside brackets. The items are not evaluated.

Standard functions

Comparison functions

<  <=  <>  =  >=  >  have their usual meanings. String comparison is case-insensitive.

==   strict-equal?  strict-not-equal?  is strict comparison; string comparison is case-sensitive, and different numeric types are unequal.

same?    is the identity test (same memory location).

Logic functions

and value1 value2
For integers, performs a bitwise and. For logical values, evaluates both and performs a logical and. May be used as infix.
all expression-block
Evaluates the expressions in order, returning a false or none value if one is encountered, otherwise returns the last value in the expression-block. Returns true if the expression-block is empty.
or value1 value2
For integers, performs a bitwise or. For logical values, evaluates both and performs a logical or. May be used as infix.
any expression-block
Evaluates the expressions in order, returning the first value other than false or none, otherwise returns none. Returns none if the expression-block is empty.
not value
Performs a logical not. Returns true only for false and none. For integers, use complement.
xor value1 value2
For integers, performs a bitwise exclusive or. For logical values, performs a logical exclusive or. May be used as infix.

Control functions

Choice functions

if condition then-block
If the condition is true, evaluate the then-block. There is no else; for an if-then-else like construct, see either.
 
either condition true-block false-block
If the condition is true, evaluate the true-block, otherwise evaluate the false-block.
switch value case-block
switch/default value case-block default-block
The case-block is a block of keys, with each key followed by an action block. The action whose key matches the value is executed. If the default refinement is given, and no key matches, the default-block is executed.
random/only series
Choose a random value from a series.
Example: do random/only [[print "yes"] [print "no"]]

Loop functions

loop count block
Evaluates the block count times.
while condition-block block
Evaluates the block until the condition-block becomes false.
until block
Evaluates a block until the result of the block becomes true.
repeat word value block
repeat word value copy/deep block
If the value is an integer, the block is executed with the word equal to each value from 1 to the value, inclusive. If the value is a series, the block is executed with word equal to each item of the series. The body argument is modified.
for word start end increment block
The block is evaluated with word equal to start, then start+increment, then start+2*increment,..., and finally end.
forall series block
Steps through the series, starting at the current location, and evaluates the block. Common usage is to set the word to the head of the block, and to leave the loop with the work set at the tail. See head, next, tail.
foreach words data block
The words must be a word or block of words. The words are set to the first elements of the data, the second elements, etc., and the block is evaluated for each set.
forskip word skip block
The word must evaluate to a series. The block is executed for the first element, the first+skip element, etc. Useful for stepping through e.g. a key-value series.
forever block
Executes the block repeatedly.
break
break/return value
Breaks out of any kind of loop. The second form returns a value for the loop.

Functions for stepping through a series

Series (blocks, strings, etc.) behave differently than in other languages. You have a current position in the series, from which the remaining elements of the series are visible, but you can move forward and backward from that position.

head series
Returns the series, beginning at the first position.
head? series
Returns true if at the beginning of the series.
next series
Returns the series, beginning at the next position.
back series
Returns the series, beginning at the previous position.
tail series
Returns the series, beginning just after the last position (hence, the series appears empty).
tail? series
Returns true if at the tail of the series.
at series index
Returns the series, indexed from the current position. at series -1 is equivalent to back series; at series 0 and at series 1 are both equivalent to series; and at series 2 is equivalent to next series.
index? series
Returns the current position in the series, counting the head as 1.
find series value
Finds the value and returns the series beginning at that value, or none.
Refinements: /part, /only, /case, /any, /with, /skip, /match, /tail, /last, /reverse.
first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth, last
Returns the element at the given position in the series, starting from the current position.

Functions for modifying a series

append series value
Appends a value to the tail of a series and returns the series head.
/only -- Appends a block value as a block.
change series value
Replaces the value at the current position in the series with the new value, and returns the remainder of the series. Given a series as value, replaces the same number of old values with the new values.
/part count-- if the value is a series, replace count elements.
/dup count-- uses the new value count times.
/only use the replacement series as a single value.
insert series value
Inserts the value into the series before the current location and returns the remainder of the series.
If the value is a series compatible with series, all the elements are inserted.
/part count-- if the value is a series, insert count elements.
/dup count-- insert the value count times.
/only inserts the series as a series.
remove series
Removes the value at the current location series. Returns the remainder of the series.
/part countremoves the specified number of values.
remove-each word series block
For each element word in the series, remove it if the block evaluates to true.
replace series old-value new-value
Finds and replaces the old-value with the new-value in the series.
/all will replace all matching values.
/case makes the search case sensitive.
reverse series
Reverses the remainder of the series, returning the reversed part.
/part count reverses count elements, returning the series from that point.
sort series
Sorts the series in ascending order.
/reverse sorts the series in descending order.
Other refinements: /case, /skip, /compare, /part, /all.
join value rest
Adds the value to the beginning of rest, returning a new instance of the same datatype as the value.
rejoin block
Evaluates the elements of the block and concatenates them. The first element of the block determines the result type.

Functions for evaluating a block

do block
Evaluate the contents of the block. The value of the (one) last expression in the block is the value of the block. (Actually, do will evaluate just about anything.)
reduce block
Evaluates each expression in the block and returns a list of results.
compose block
Evaluates each parenthesized expression in the block, leaves unparenthesized elements unchanged, and returns a list of results.

IO functions

Console interaction with the user

print value
Prints the value followed by a newline. Caution: Does not print brackets when printing a block; see probe.
prin value
Prints the value, not followed by a newline. Caution: Does not print brackets when printing a block; see probe.
probe value
Prints the value in Rebol-readable form, and returns the same value. Useful for debugging, as it can be inserted without interfering with the code.
mold value
Returns a REBOL-readable string. If you want to print blocks as blocks, print mold my-block.
input
Reads and returns a line from standard input, discarding the newline.
/hide replaces characters with asterisks as they are typed.
ask question
Prints the question, and trims and returns the user's response. Equivalent to prin question trim input.
/hide replaces characters with asterisks as they are typed.
wait value
Waits for the given amount of time, or for an event from a port.

GUI interaction with the user

alert message
Displays an alert box containing the message and an OK button.
confirm yes-no-question
Opens a dialog box with the question and "Yes" and "No" responses. Returns true or false.
/with [true-response false-response] does the same, but with different labels on the buttons.
request question
Opens a dialog box with the question and "Yes", "No", and "Cancel" buttons; returns true, false, or none, respectively.
Refinements: offset xy, /ok, /only, /confirm, /type icon, /timeout time.
request-text
Allows the user to input a line of text.
Refinements: /offset xy, /title, /default string.
request-list title block
Lets the user choose from a list.
Refinement: /offset xy.
request-file
Lets the user choose an existing file.
/save lets the user choose a location to save a file.
/file provides a starting file or directory name.
Other refinements: /title title-text button-text, /filter filter, /keep, /only, /path.
request-dir
Lets the user choose a directory.
/dir file sets the starting directory.
/keep keeps the previous directory path.
Other refinements: /title title-text, offset xy.

Navigation functions

what-dir
pwd. Returns the current directory.
change-dir dir
cd. Navigates to the given directory, and returns it.
make-dir dir
mkdir. Creates the given directory.
/deep -- also make subdirectories.
exists? value
Returns true if the file or URL exists.
file? value
Returns true if the value is a file.
dir? value
Returns true if the value is a directory or the URL of a directory.
url? value
Returns true if the value is a URL.

Data I/O functions

read source
Reads in the entire contents of a file, URL, or port-spec as a single string containing newlines suitable for the current platform.
/lines -- Discards newlines and reads as a sequence of strings.
/with end-of-line -- replaces newlines with the given character or string.
Other refinements: /binary, /string, /direct, /no-wait, /part size, /mode args, /custom params, /skip length.
write destination value
Writes the value, as text, to a file, URL, or port-spec.
/lines -- write each item in the block of values on a separate line.
/append -- appends to the destination.
/with end-of-line -- uses the character or string for the end-of-line character.
Other refinements: /binary, /string, /direct, /no-wait, /part size, /mode args, /allow access, /mode args, /custom params.
load source
Loads in Rebol code from a file, URL, string, or binary value. If the source is a directory, and ends in a forward slash, returns a list of files. See also: do.
/header -- if a header is present, make it the first element of the block.
/next - Load the next value only. Return block with value and new position.
/all - Load all values. Does not evaluate Rebol header.
Other refinements: /library, /markup.
save destination value
Saves Rebol code to a file or URL.
/header block -- save with header data.
Other refinements: /bmp, /png, /all.
rename old-name new-name
Renames a file.
delete target
Deletes the file, URL, or empty directory.
/any -- to allow wildcards.

Defining functions

To define a function with parameters and local variables: function spec locals actions
Example: plus: function [x y] [sum] [sum: x + y  sum]

To define a function with parameters: func spec actions
Example: plus: func [x y] [x + y]

To define a function with no parameters: does actions
Example: sing: does [print "do re mi"]

To define a function with local variables but no parameters: has locals actions
Example: bigrand: has [x y] [x: random 10 y: random 10 max x y]

The value of a function is the last value in the block of actions. To return a value before reaching the end, use return value; to return no value, use exit.

To test if a word is a function: function? word

To see the source code of a function: source functionName

The spec argument is a block. The first element of the block may be a documentation string (printable by help functionName), the remaining elements are words representing formal parameters. Each word may be followed by a block containing the acceptable datatypes for that parameter. To include refinements, use words prefixed by a slash. To specify local variables, use /local followed by those variables. For example,

    sum: func [nums [block!] /average /local total] [
        total: 0
        foreach num nums [total: total + num]
        either average [total / (length? nums)][total]
    ]

Some useful links

There is a lot of very good documentation and tutorials on the web. Here are some to start with.