The Red Programming Language
red-lang.org
red-lang.org
I always found that fascinating too.
Although the sequence! and the object! datatype in Rebol are not subtypes of each other they have similar semantics (pass by reference, explicit copying, mutation performed in place by built-in functions like sort).
Objects in Rebol and their literal representation are actually pretty interesting, too. Douglas Crockford cites Rebol as one of the inspirations for JSON, and you can see why when you look at an example:
>> example: make object! [
var1: 10
var2: var1 + 10
var3: now/time
set-time: does [var3: now/time]
calculate: func [value] [
var1: value
var2: value + 10
]
]
>> print mold/all example ; mold/all serializes data
#[object! [
var1: 10
var2: 20
var3: 21:42:34
set-time: #[function! [][var3: now/time]]
calculate: #[function! [value][
var1: value
var2: value + 10
]]
]]
I haven't read much Rebol application code but as far as I understand serializing objects and storing them on disk as plain text is the norm for configuration and persistence.The other interesting thing about my research on Wikipedia was the tangent it took me on. I started reading about other other homoiconicity languages that I hadn't heard of; and that lad me to a page about the programming language "Curl"[2] (not related to the cURL HTTP client that most Linux / UNIX sysadmins would be well versed in). Curl is very interesting as it merges the different stacks of web development (markup, style sheets and scripting engine) in a unified language that can still be abstracted separately if one so chooses. Baring the syntax, it was exactly the type of concept I was suggesting a little while back when myself and a few friends were discussing ideal world scenarios of how we'd reinvent the web-development stack.
Anyhow, Red is definitely an interesting language in itself. But it's always a bonus when one interesting post on HN leads you on a journey of a few other discoveries.
[1] http://en.wikipedia.org/wiki/Homoiconicity
[2] http://en.wikipedia.org/wiki/Curl_%28programming_language%29
Actually it didn't. Javascript is not homoiconic. JSON just happens to be almost like a homoiconic version of the Javascript array and dict data types, but that stops there.
For one, there are some restrictions to what can be valid JSON that are not the same for JS code. And then there are functions etc, which are not in JSON.
And the idea that JS is somehow related to Scheme isn't really true (despite being repeated even by Eich). What it has common with Scheme, tons of other languages that nobody will ever say of them to be related to Scheme have. What it doesn't have in common is what makes Scheme scheme. See also:
http://journal.stuffwithstuff.com/2013/07/18/javascript-isnt...
Javascript was inspired by Scheme, and obviously other languages as well. Since we're referencing Eich, he has also personally talked[1] about how he was hired at Netscape to write a Scheme for the browser and how he later developed a new language with ideas borrowed from Scheme (as well as Self, TCL and a few other languages IIRC). Thus there are obviously going to be some inheritance from Scheme in Javascript; even if they are conceptually very different languages and even if those qualities inherited are also shared amongst a multitude of other languages.
You see, something doesn't have to be exactly like, nor even uniquely like, to still have inheritance. Much like how derivative works in art where the predecessor stands up as an original piece - separate from the parent's vision - despite sharing the same lineage. Such is the beauty of derivative works - you can take inspiration from the preceding material yet still invent something different.
So that's what I meant when I said that Javascript inherited homoiconicty from Scheme (though obviously I was wrong about Javascript being homoiconic itself - and I thank you for that correction)
Well, I didn't argue that JS isn't Scheme (that is of course obvious).
I argued that it doesn't seem to have anything specifically Schem-y about it.
Eich says it was "inspired by scheme", but I, like the article author, fail to see any such inspiration.
JS doesn't have Scheme syntax, nor does it have Scheme semantics (of course that's obvious to see). It also doesn't have the most celebrated Scheme features (from homoiconicity and macros to tail call optimization). And all the other stuff (GC, closures, etc), was already available in languages predating Scheme, and he knew that (Lisp, Smalltalk, etc).
And he even mentions the language Self, which is a much closer to JS than Scheme. I think he mainly just wanted to do a Scheme, but INSTEAD he did JS, which is mostly Self, Java syntax and a few other ideas thrown together.
For example, in Scheme, I can easily generate data structures and interpret them as code to be executed or as data to be manipulated. For example, here I can generate code corresponding to a given factorial, and also muck with it.
> (define (fact-code n)
(if (= n 0) 1 `(* ,n ,(fact-code (- n 1)))))
> (fact-code 4)
(* 4 (* 3 (* 2 1)))
> (eval (fact-code 4) (the-environment))
24
> (eval (replace '* '+ (fib-code 4)) (the-environment))
10
We can write a function similar to fact-code in Rebol, which I'm borrowing from an earlier comment[^1] >> fact-code: func [n] [either n = 1 [1] [compose [(n) * (fact-code n - 1)]]]
>> fact-code 4
== [4 * 3 * 2 * 1]
>> do fact-code 4
== 24
>> do replace/all fact-code 4 '* '+
== 10
There is no analogous way of generating and manipulating JavaScript code using JavaScript. If all JS code could be understood as JSON that then could be fed back into JavaScript and manipulated there, then it would be homoiconic.[^1]: Borrowed from this older comment with a minor name change https://news.ycombinator.com/item?id=5809980
What made me believe JS / JSON were homoiconic was down to the following vulnerable method of loading a JSON file:
var obj = eval (json);
But after reading your post, I can see how this differs from homiconicityOf course, if Red is not so much a DSL as it is a DSL-authoring language like REBOL, then I share your confusion. For a general purpose language, I'm not sure what the advantage would be of making those primitives/literals rather than components within the standard library.
From Rebol console (these types not yet all implemented in Red):
>> red + blue
== 255.0.255
>> 192.168.100.123 and 255.0.0.0
== 192.0.0.0
>> yesterday: now/date - 24:00
== 15-Nov-2014
>> in-one-year: now + 365
== 16-Nov-2015
>> yesterday < in-one-year
== true
Rebol provides around 55 datatypes, with a good part of them having a specific literal form. The standard library is actually built-in the language, through this rich set of datatypes (each datatype overloads the basic language functions and operators). You don't need to "import" any of it, it's right there, but almost transparent to the users. The footprint for that is small, the full uncompressed runtime in binary form is about 500KB only.This unusual (but very effective in practice) approach, is one of the features that got me hooked to Rebol in the first place, 15 years ago.
[1] http://www.rebol.com/docs/core23/rebolcore-16.html#section-3...
[2] http://www.rebol.com/docs/core23/rebolcore-16.html#section-3...
[3] http://www.rebol.com/docs/core23/rebolcore-16.html#section-3...
About the syntax and semantics, in a nutshell, it's a Lisp without parentheses and with infix operator support. Tokens are separated by a whitespace or a delimiter (very few of them). Code is a tree of lists (called "blocks" in our local jargon), blocks are delimited by square brackets [].
You can have a look here [1] for a larger code and syntax example.
red>> .1 + .2 + .3 = .6
== true
red>> .1 + .2 + .3 - .6
== 1.110223024625157e-16
This doesn't feel right to me. I usually would expect equality to be a strictly exact thing. This is bound to cause some problems in code that assumes IEEE-754 has been implemented exactly. red>> .1 + .2 + .3 == .6
== false
red>> .1 + .2 + .3 = .6
== true
I'm not sure if that syntax is the wisest choice, but in the absence of arbitrary precision arithmetic it seems a very good concept, to avoid common IEEE-754 surprises.They appear to be implementing it along these lines: http://randomascii.wordpress.com/2012/02/25/comparing-floati...
>> .1 + .2 + .3
== 0.6000000000000001
>> type? 0.1
== decimal!
>> $.1 + $.2 + $.3
== $0.6
>> type? $0.1
== money!
Red will most likely get this soon but perhaps with a different nomenclature (Red as already renamed decimal! to float!). if float-1 = float-2 [
; do something
]
In other languages: if (float-1 - float-2) < EPS {
// do something
}
Obviously, Red's way is more natural and readable. :)Red looks awesome in the long run, the main weirdness being its refusal to follow standard math operator precedence [2].
Although Red's macro/DSL buildup skips a ton of intermediate bloat, someone needs to write a normal server framework to interact with standard industry data sources. When it becomes easy to add a Red microservice to an architecture, Red can enjoy an explosion of adoption as Go has.
[1] http://rebolforum.com/index.cgi?f=printtopic&topicnumber=27&...
[2] http://stackoverflow.com/questions/26514041/fixing-the-rebol...
Regards,
Arnold
>> print 1 + 2 * 3
== 9
>> print math [1 + 2 * 3]
== 7Make no mistake: both REBOL and RED have an extremely powerful underlying model model to help solve problems. In a world of containers and micro-services "something like these" will emerge.
If nothing else, that's a reason to follow them - between Go and RED/REBOl you can see a glimpse of computing as it will be.