Joe Ganley

Lisp in JavaScript



I wanted to get a feel for just how powerful JavaScript is as a programming language (as opposed to just a scripting language), so I sat down one evening and wrote this. It turns out that it was quite good for this application, since it is so flexible - dynamically sized arrays are used throughout, and associative arrays make the symbol table quite easy.

A number of Lisp instructions are implemented (see below). The choice of instructions and some of the implementations of the composite functions were taken from Roger Rohrbach's Lisp in Awk interpreter. The syntax is standard, and only integer arithmetic is available. Primarily because it is easy to implement, scoping is dynamic as in original Lisp and unlike modern Lisp or Scheme.

Since this is pretty much a toy, it doesn't do much in the way of error handling. However, it should work on correct Lisp code; if it breaks on code you believe to be correct, please send me mail.

To see the source code, just View-Source on this page; but see the copying restrictions below.

Update 2010:

I wrote this in 1997, just for fun and as a vehicle for learning JavaScript. It's just a toy, and at this point a rather outdated toy at that. People are still welcome to send bug reports, but know that in all likelihood I'm not going to fix the bugs you report.

Meanwhile, there are a few other Lisps in JavaScript that might interest you:

The interpreter implements the following instructions as primitives:

In addition, the following are defined as composite functions; i.e. they're defined in Lisp itself as functions of the above primitives.

    The standard car and cdr composites cadr, cddr, caar, cddr, cadar, cddar, cdadr, caddr.

    (null s)
    (not s)
    Returns t if s is nil, nil otherwise.

    (equal x y)
    Tests equality, where equality of lists means structural equality, not that they are the same object as with eq.

    (append x y)
    Appends the lists x and y.

    (member e s)
    Returns t if e is in the list s, nil otherwise.

    (last s)
    Returns the last element in the list s.

    (reverse s)
    Returns the list s with the elements in reverse order.

    (remove e s)
    Returns s with all occurences of element e removed.

    (mapcar f s)
    Returns a list resulting from applying the function f to each element of s.

    (apply f s)
    Calls the the function f with argument list s.

    (len s)
    Returns the number of elements in the list s.

    (flatten s)
    Returns the flattened version of the list s, i.e. a list containing the atoms in s in order.

You are free to copy this code and modify it as you wish, provided that (a) my header comment in the code is not removed, (b) you make apparent as both a comment in the code and visibly on the web page that contains it that you have modified it, and (c) the following message appears visibly on the web page that contains the code: