First, install Node.js and then all necessary modules:
$ npm install
core already contains the full Ralph runtime and compiler
To start a local, Node.js-based REPL, run:
$ NODE_PATH=core node repl.js
To start a remote, browser-based REPL, install browserify,
generate the browser evaluator, start the REPL with the
index.html in your browser:
$ NODE_PATH=~/node_modules:core browserify evaluator.js -o evaluator.out.js
$ NODE_PATH=core node repl.js --remote
To compile a simple "Hello, world!" program:
(define-module hello import: (ralph/format-out) export: (hello)) (define-function hello (name) (format-out "Hello, %s!" name))
hellomodule. The compiler outputs files into
$ NODE_PATH=core node -e "require('ralph/compiler')['compile-module']('hello')"
Run the program by opening the
hellomodule and calling the
$ NODE_PATH=build node -e "require('hello')['hello']('World')" Hello, World!
There is unfortunately no API documentation. The module
contains the core runtime and the standard library.
The manual of Prefix Dylan can be used as a reference and is a good introduction into the language.
instead of implementing its own list data structure based on objects. Arrays can be
created using the
 syntax (e.g.
(first [1 2 3])).
Symbols may contain any character which is not otherwise syntactically significant
(e.g., introduces a number, an array, etc). The character sequence
:: in symbols
is treated as the separator for fully-qualified symbols: The first part is
the module name, the second is the symbol name.
Keywords have the same syntax as symbols and end with a colon (e.g.,
The syntax for the canonical true value is
#t, for the canonical false value
In parameter lists,
#rest is used to introduce the name of the variable containing
the additional arguments, and
#key is used to introduce keyword parameters.
A single quote is used for quoting. A backquote is used for syntax-quoting (see macros).
A semicolon indicates the start of a comment.
The special operator
passed to it are directly emitted as-is. Numbers are first converted to strings, and
symbols are properly renamed. Other forms are not supported.
For example, the following Ralph code
(bind ((delta 3)) (%native "x += " delta " * " 2))
var delta__1 = 3; x += delta__1 * 2;
Ralph's compiler knows nothing about the global
x and there is no need to
declare it exists.
The utility macro
(. (%native "console") (log "Hello, %s" "World"))
would compile to:
console.log("Hello, %s!", "World");
Ralph also integrates well with Node.js. To be able to use a Node.js module
in Ralph, place a
.rm file (ralph module definition) in
src that specifies
the name, it is native (
native?: #t) and the definitions it is exporting.
For example, a basic definition for the Node.js module
vm could look like:
("vm" native?: #t exports: ("createContext" "runInContext"))
Ralph supports hygienic macros through Clojure-like syntax-quoting.
In a separate module, define the macro using
define-macro. In the module you
want to use it, import the module during compilation using the
option in the
For a full example, see
can be compiled using.
$ NODE_PATH=core:build node -e "require('ralph/compiler')['compile-module']('ralph/macro-test.a')"
The section "Macro system" in the paper contains more details.
The compiler can be recompiled and all tests can be run using:
Ralph is not actively maintained.
If you have questions, are interested in using it, or even would like to continue its development, just open a new issue!