(Sibilant: JavaScript with a LISP)



Sibilant is an s-expression language that compiles to readable and idiomatic JavaScript. Sibilant is built on a simple macro system that gives you compile-time control over the output JavaScript as well as providing tools to smooth over some of JavaScript's historical idiosynchracies.

If you'd like to follow along in a local REPL,

bash> npm install -g sibilant
bash> sibilant
sibilant> (console.log "welcome to sibilant")
console.log("welcome to sibilant")
welcome to sibilant

All of the code in the left column for the rest of this document is editable and is compiled by your browser as you type.

Here's an quick sample of sibilant code (inspired by the first example on coffeescript.org).

And here's the canonical node example from nodejs.org

Numbers and Strings

Numbers should look pretty familiar. Use commas to enhance readability.

Strings are surrounded by double quotes. Multi-line strings are supported! Use a backslash to escape a double-quote inside of a string.


Variable names may include letters, the period (.) and the hyphen (-). Lower case letters are idiomatic. They may end with a question mark (?) or with a bang (!). They may start with a sigil ($).

Objects and Arrays

Objects and Arrays are supported as a proper subset of JSON.

Idiomatic sibilant skips any unnecessary commas and colons that do not contribute to readability

Arrays and objects contents are accessed with the get and set macros

Defining variables

Since sibilant is a tool for writing JavaScript, it exposes the var keyword with an identically named macro.

To modify an existing variable (assignment), use the assign macro.

Defining functions

Sibilant avoids hoisiting by defining functions as variable by default.

If your function name includes a dot, it will not be defined as a variable.

Lambdas and Thunks

Lambdas are how sibilant defines anonymous functions.

Because anonymous functions are is used so often in JavaScript, sibilant includes a shortcut to define lambdas, #.

Thunks are zero-arity lambdas (anonymous functions that accept no arguments). A shortcut for this is the #> macro.


Sibilant provides two primary conditional macros: if and when. When is the simplest, only executing the subsequent block when the conditional evaluates to a truthy value. All conditionals in sibilant are expressions and evaluate to some value. This is done by introducing a scope with a self-executing function.

The `if` macro supports any number of branching paths. If the bodies of the branching paths needs more than one expression, the `do` macro is used.


Iteration is an example of a macro that can easily be redefined for different compilation contexts. Since the default compilation environments are modern browsers and node, the `each` macro compiles to `[].forEach`. If you needed to compile sibilant to an older JavaScript, the each macro could be easily modified to support a `for` loop.

Further Reading

For further documentation, check out docs.sibilant.org and ask questions on gitter or github issues.