Notable facts about Rebol programming language
rebol programming-language
Rebole is an unusual open-source (from v3) functional programming language with infix operations.
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 +
, -
or ?
:
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
199.4.80.7 ; 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
info@rebol.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 =
/==
mistakes.
Rebol has unquote-like operator
Code is data that is executed implicitly in many cases, but also can be executed explicitly by do
operator.
do [print 1 + 2] ; 3
Blocks []
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
Many languages more or less have this property, for example, any JavaScript program can always be minified to a complete mess, but Rebol does this without parentheses and semicolons!
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 if
-like expressions: if
and 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
or 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
and 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]
]
Here delay
will change on make-timer
call, affecting timer
function.
This is unusual for functional language.
Other facts
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!
Conclusion
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 ==
problem.
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
because print
in the last line requires an argument. But this (with colon added to a parameter in function declaration) runs:
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.
Links
There's Rebol inspired Red programming language
shitpoet@gmail.com