Notable facts about Rebol programming language
Rebole is an unusual open-source (from v3) functional programming language with infix operations.
Side note: I've created a simple site, where you can try Rebol 3 scripts without installation of Rebol 3 interpreter.
Rebol was closed/open source
The documentation says that core component of Rebol (I think it contains interpreter and a few native functions) is closed:
This is what makes REBOL operate identically over all systems and devices; therefore, we're strict about it.
And everything else (standard functions lib, for example) are open.
But there is official github repo.
And there is a compilation guide from the author of Rebol.
Rebol has minimalist "toolset"
Rebol is an way under 1MB single binary executable file.
Rebol has minimalist file name extension
Rebol scripts (called rebols!) has
r file name extension. The shortest possible if not considering an empty extension as in bash. (Through
r3 is considered for Rebol 3 now.)
Rebol has liberated identifiers
The language has somewhat significant white space, because identifiers can include symbols like
a + b - c ; arithmetic expression a+b-c ; identifier print length? "example" ; 7
Also identifiers can start with non-letter. So
+ is valid identifier (an word in Rebol).
Rebol has rich set of literals
Rebol allows to create tuples using
3.1.5 ; version numbers 255.255.0.100 ; colors 184.108.40.206 ; network addresses
But I can not understand how does it differentiate them from floating point literals, like
3.14 (they are supported by Rebol.)
The language has built-in datetime literals:
20-Apr-1998/12:32 ; date and time 20-Apr-1998/12:32-8:00 ; with timezone
URL and other "special strings":
640x480 %images/photo.jpg %../scripts/*.r http://www.rebol.com email@example.com <div class='marx'>
All code in Rebol is data
Code is data:
>>> if false [bla bla] none
Not very interesting for functional people, but very interesting for others.
In general the evaluation of values of "variables" is lazy:
>> sizes: [small med big] == [small med big] >> print sizes ** Script error: small has no value ** Where: print ** Near: print sizes >> sizes == [small med big]
Rebol has special prefix and postfix colon "operators"
Colon is assignment operator when placed right after identifier:
blk: [print 1 + 2] if true blk ; 3
And it is an quoting operator (like in Ruby or Julia) when placed right before identifier:
>> print print Script error: print is missing its value argument >>> print :print make native! [[ "Outputs a value followed by a line break." value [any-type!] "The value to print" ]]
In both cases colon creates single fused value with the identifier it is applied to:
length? [a: 1] 2 length? [:a 1] 2 length? [a = 1] 3
Equals operator is used for comparison that is a good thing, no more
Rebol has unquote-like operator
Code is data that is executed implicitly in many cases, but also can be executed explicitly by
do [print 1 + 2] ; 3
 are passive lists like in clojure.
do also can execute strings or files (later - by file name literal).
Rebol functions have refinements
Refinements are additional modes of existing functions:
print copy "example string" ; example string print copy/part "example string" 7 ; example
The (manual)[http://www.rebol.com/r3/docs/guide/code-words.html] says it makes names easier to remember.
I don't know if it's the case, but it can make functions more autocomplete-friendly. Like with object members in OOP languages.
We also did not use dot because we didn't want to lose the ability to specify file names as refinements (with suffixes that use dot, like that shown above).
So I assume the refinements can be dynamic, not totally predefined (?).
Refinements replace boolean arguments that are false by default, and specified not by passing
true somewhere in the arguments list but by specifying a name of refinement. I think it's good, though it leaks names of parameters so can potentially create a problem in case of refactoring.
Rebol programs can be a complete mess
Any Rebol program can be written as one-liner
>> print "reading web page..." data: read http://www.rebol.com print length? data reading web page... 4081
Rebol has linear precedence for infix operators
All operators have the same preference:
print 1 + 2 * 3 + 4 * 5 65
We've found that for most expressions, linear precedence works as well or better than multilevel precedence, and you don't have to memorize all the precedence rules (which once you add comparisons and logic can become quite complex and few people remember them.)
This linear precedence is interesting but creates problems because the priority of operations is still higher than priority of functions:
if (length? "a string of chars") > 10 [print "ok"]
Rebol has two ifs
There are two
either. First is binary (two arguments - condition and expression), second is ternary (condition, true branch expression, false branch expression).
I think this approach was selected because all Rebol functions must have fixed arity, so we can not have two overloads of
if with optional argument.
The manual says:
A common mistake is to add a second block to if or forget the second block on either. These are both wrong, but they may or may not cause a run-time error:
So may be two different names for
if-else allow programmers to avoid this mistakes too.
Rebol has (no) local variables
All variables are global by default and one creates local variables through a hack:
print-it: func [/local str] [ str: "" insert str "ha" print str ] print-it ha
And even with this hack the value is static in C sense:
print-it haha print-it hahaha
The tutorial guide does not state it but full Rebol 3 docs say that there is actually a way to create local variables:
print-it: function [str][ str: "" insert str "ha" print str ] print-it
But this does not run for some reason:
** Script error: str has no value ** Where: print-it try do either either either -apply- ** Near: print-it
May be the feature is work in progress...
Rebol has no closures
Captured variable values will change on every call of outer function:
make-timer: func [code delay] [ timer: func [time] [wait time + delay] ]
delay will change on
make-timer call, affecting
This is unusual for functional language.
It seems like collections have state - current index position. But I was unable to check that in Rebol 3.
There are type literals in Rebol like
none! number! string! error!
and so on and they can be assigned to variables!
Rebol is a bit unusual dead programming language.
It has no proper lexical scope and no closures, and seems to have no proper local variables.
But has very minimalist syntax (the one of the purest I've seen) and has some interesting ideas like refinements and built-in literals for many types of data. Here it is similar to Bosque - a new programming language from Microsoft Research. Also Rebol shows an example of infix operators in lisp-like languages.
Another interesting idea is with colons eliminating the
Btw formal parameters in function declaration can have prefix colon operator too - in this case argument will not evaluate.
For example, this will fail with script error
f: func[f][ print f ] f print
f: func[:f][ print f ] f print
and prints "print" - name of the function.
So this is an example where we control evaluation of function parameters. But this works only for a single word parameters as I understand. In other words one can not write an alternative
if that would require no
 for its body using this technique, because the body will have variable length.
What I like about Rebol the most is its ambitious mood.
There's Rebol inspired Red programming language