2009-04-24

REBOL

When I first looked at REBOL, I didn’t think much of it:

foreach e [1 2 3] [
   print e
]

Pretty obvious what this does, and it’s the sort of thing you’ve seen a million times, eh? Not to mention the square brackets …

But then I saw stuff like this:

write/binary %Google.html read/binary http://www.google.com

That started to pique my interest! I can't think of another language in which writing the contents of a URL to a file are so concise. It might as well be wget or curl.

I noticed a few other strange things about this syntax as well. First, the URL was not quoted. It was just written out as is. And the file name was prefixed by a percent sign. I had to know more about this, and what I discovered was much deeper than I ever expected.

Like all programming languages, REBOL has tokens whose type can be determined by their lexical form. To give a common example, when an interpreter or compiler encounters the token 3, it interprets it as an integer (of some kind). These kinds of tokens are usually known as literals. Most languages have string and numeric literals, and that’s about it. REBOL on the other hand has a lot of literals: strings, numbers, URLs, blocks, parens, paths, words, files, and so on.

Here are some examples:

ExampleREBOL Type
3integer!
3.2decimal!
"fish"string!
{fish}string!
http://www.google.comurl!
ftp://ftp.nowhere.comurl!
%Google.htmlfile!
printword!
word:set-word!
'printlit-word!
read/binarypath!
[1 2 3]block!
(1 2 3)paren!

There are many more. As you can see, a few of these have equivalents in other languages, but most don’t. In fact, some of these look suspiciously like the kinds of things in which a compiler or interpreter would be interested. That’s true, and it’s the basis of what's known as the data exchange dialect.

Let’s digress a bit. REBOL is composed of a hierarchy of dialects. There are several built-in dialects, and REBOL gives developers the ability to create their own. The basis of all the dialects is the data exchange dialect, which isn’t a programming language per se. It's just a free-form sequence of literals that can be interpreted however one wishes. For example:

[http://www.google.com http://www.yahoo.com] fetch no-one@nowhere.com

If we were to replace literals above with their types, we'd get

block! word! email!

(Yes, email addresses are another literal data type.) The data exchange dialect can be used much like XML. You can pass around chunks of it and the REBOL interpreter will happily tell you what the types and values of the literals are. It makes for a much better XML than XML, in my opinion. Here's an example:

data: load "[http://www.google.com http://www.yahoo.com] fetch no-one@nowhere.com"
foreach literal data [
 print type?/word literal
]

The code above prints out the following:

block!
word!
email!

When the load function is passed a string, it interprets the contents of the string as a sequence of literals, and returns a block! containing those literals. Thus, the data variable has the following value:

[[http://www.google.com http://www.yahoo.com] fetch no-one@nowhere.com]

So, if the block above is an example of the data exchange dialect, what dialect is actual programming code written in? The DO dialect. Ordinarily, when the REBOL interpreter starts processing a file, it assumes that the file is written in the DO dialect. Like all dialects, the DO dialect is a stream of literals whose types are determined by the rules of the data exchange dialect. However, what is done with them afterwards is determined by the rules of the DO dialect.

For example, when the DO dialect encounters the literal* print, it says, "Ah! This is a literal of type word!". It then looks up the value of that word and finds that it points to a function taking a single argument. It then prints the value of that argument to standard output. E.g.,

print "REBOL"

This does exactly what one would expect.

All of this barely scratches the surface of REBOL. There's the syntax of the DO dialect, those strange beasts called words, Bindology and contexts, and so on. The purpose of this post was to get you interested. Hopefully you'll read more at rebol.com.

*Note that strictly speaking, print is a literal in the data exchange dialect, but a token in the DO dialect. However, in the interests of reducing confusion, I stuck with the former term.

5 comments: