People who speak English understand messages such as "turn on the light" or "record TV channel 7 at 8 pm." But can your computer understand the same messages? The question is not whether your computer can understand English, but rather, can it understand these specific messages? In other words, is it possible to share a common language with your computer, even if it's not exactly English?

This is the goal of REBOL, short for "Relative Expression-Based Object Language." REBOL was designed to make it easier to communicate between computers, or between people and computers, using context-dependent sublanguages. REBOL is unlike traditional programming languages such as C, Basic, or Java. The language has no keywords and little syntax. Although it can be used for programming, writing functions, and performing processes, its greatest strength is the ability to easily create domain-specific languages or dialects.

In addition, REBOL is a highly polymorphic and reflective language. The former means that the language applies its functions to a wide variety of datatypes in a consistent manner. The latter indicates that the language can be dynamically introspective about itself. This property is quite difficult to obtain in language design, but allows REBOL to be descriptive and self referential. In fact, REBOL is metacircular: It is able to serve as its own metalanguage, eliminating the need for preprocessing and macros. The result is a language with a powerful and dynamic means of expression.

REBOL scripts are machine independent and run on 37 different CPU/OS platforms. The language has several networking protocols built in, including HTTP, FTP, NNTP, SMTP, POP, Finger, Whois, Daytime, and DNS. In addition, it handles multiple proxy servers and can communicate directly at the TCP/IP level. Finally, REBOL is compact, requiring only a 200 KB download; it can be downloaded free of charge from http://www.rebol.com/.

REBOL Programming

REBOL is not a conventional language. It breaks a number of rules. For instance, REBOL has more than 40 datatypes built in (contrasted to languages such as C that have five or six datatypes). This lets you write values such as dates, times, money, e-mail, HTML/XML tags, and URLs directly in a script using a format that is already familiar to you. In addition, the datatypes are always part of the system. You don't need to hunt around for libraries or include files.

This simple script creates a network agent to check a web site every 10 minutes. If the web page fails to download, an e-mail is sent to the webmaster:

forever [ if error? try [ read http://www.site.dom ] [ send [email protected] "Site is down." ] wait 0:10 ]

This example checks every hour to determine if a web site has changed:

old-sum: checksum read http://www.site.dom until [ wait 1:00 old-sum <> checksum read http://www.site.dom ] send [email protected] "Web site changed!"

The brackets [] indicate blocks, which can hold both code and data values. They can be of any length and may contain other blocks. The values within a block can be of various datatypes. These values are written in free format, with no significance to spacing or lines. Table 1 shows the available datatypes.

Table 1: Primary REBOL datatypes. (a) Numerical datatypes; (b) character datatypes; (c) block datatypes; (d) word datatypes; (e) function datatypes; (f) object datatypes; (g) special datatypes.

REBOL is a symbolic language. Words are used as both symbols and as variables. When used as symbols, you're not interested in their value, only what they stand for.

A block can be evaluated. This operation looks up the values for words and performs functions. The values can be passed as arguments to functions, and values are returned as results. All operations in REBOL are functions. For instance, you can write:

if time > 11:30 [print "Lunch"]

But you can also write code such as:

condition: (time > 11:30) action: [print "Lunch"] if condition action

A variable definition is done with a colon, not an equal (which is used for equality). A variable can hold a function as well as any other type of value.

It is worth noting that REBOL has no keywords and little syntax. This may seem foreign if you know C, Java, or Basic, but these features are important for creating dialects.

As mentioned earlier, REBOL is a highly polymorphic and reflective language. The reflective property can be seen when using the REBOL internal help, which uses function argument specifications to generate help information. For instance, the help lines in Example 1 were generated from the definition of the switch function. This introspective database is also used when generating error messages, as in Example 2.

USAGE: SWITCH value cases /default case DESCRIPTION: Selects a choice and evaluates what follows it. SWITCH is a function. ARGUMENTS: value -- Value to search for. (Type: any) cases -- Block of cases to search. (Type: block) REFINEMENTS: /default case -- Default case if no others are found. (Type: any)

Example 1: Help lines in REBOL.

switch 20 ** Script Error: switch expected cases argument of type: block. ** Where: switch 20

Example 2: Generating error messages.

REBOL Data Structuring

REBOL data structures are also formed with blocks. They can contain values of any datatype, including words, and the values may appear in any order. The freedom of order establishes the basis for dialects and will be explained in the next section.

The data held within blocks can be referenced by its position, tag, type, evaluation, and dialect. Referencing by position is most common for groups of fixed-size structured data. For instance, Listing One defines a block of friends and related data. The position determines where information is held. Name is first, age is second, and e-mail is third.

Listing One

Referencing data by tag is useful if the order of the data is irregular or contains entries of variable length, as in Listing Two. Words are used as tags to mark specific values. The words are not used as variables; they are just markers (similar to how XML tags its data). Similar to tags, datatypes can be used to reference specific items. Listing Three shows how you would find all e-mail addresses to send friends a quick hello.

Listing Two

friends: [ name "Bob" "Marker" age 24 name "Sally" age 28 email [email protected] phone #777-555-1111 name "Julie" "Lober" email [email protected] site http://www.juliesite.dom city "New York" ] while [friends: find friends 'name] [ friends: next friends print first friends ] friends: head friends

Listing Three

while [friends: find friends email!] [ send first friends "Quick hello!" friends: next friends ]

Another method of referencing data requires evaluation of the data block in order to set variables to specific values. Here each value is assigned to a variable. This is done when the block is evaluated, as in Listing Four.

Listing Four

friends: [ [name: "Bob Marker" age: 24] [name: "Sally" age: 28 email: [email protected] phone: #777-555-1111 ] [name: "Julie Lober" email: [email protected] site: http://www.juliesite.dom city: "New York" ] ] foreach person friends [ set [name age email phone site city] none do person print name ]