What dialect of Lisp should I use to follow along the book with?

Scheme of some sort ideally - either MIT Scheme or Racket will do nicely. I seem to recall that someone was working on a version of SICP with examples in Clojure, but it may be incomplete.

http://racket-lang.org/

Yeah, the SICP in Clojure project died pretty early on.

Quite a bit of SICP would be awkward to translate into a language that doesn't support TCO, such as Clojure.

Pardon my ignorance, but why? I haven't read SICP, but I do consider myself to be pretty good at javascript, and was thinking of using it.

TCO refers to tail call optimization, which is a useful optimization for languages such as Scheme which encourage heavy use of recursion. TCO allows the interpreter to reuse the current stack frame when a tail-recursive[1] function calls itself instead of creating a new stack frame for each recursive call.

Because javascript lacks this and many other features of Scheme/Lisp, I wouldn't really recommend using it for SICP.

[1] Tail recursive functions are recursive functions which merely return the result of their recursive call to the caller instead of further processing those results before returning. In pseudocode:

    // non-tail
    expt(b, x):
        if x == 0: 1
        else: x * expt(b, x-1)
    
    // tail-recursive
    tail-expt(b, x, ans):
        if x == 0: ans
        else: tail-expt(b, x-1, x*ans)
For these definitions:

    expt(2, 3) == tail-expt(2, 3, 1)

TCO is an optimization, it doesn't affect correctness. So you can ignore not having it, until you run out of stack.

There is a much bigger reason to stick with Scheme for SICP: all the meta-circular evaluator stuff where you learn to implement Scheme in Scheme. I supposed you could implement Scheme in Javascript, but then you'd still need to learn Scheme. And you certainly won't want to implement Javascript in Javascript.

>TCO is an optimization, it doesn't affect correctness. So you can ignore not having it, until you run out of stack.

Correct. Though CPU performance is an issue that tail recursion optimisation addresses too. For simple functions building up the stack frames and deallocating them afterwards can be more work than the function itself. For deep recursion stack space is the problem you usually hit first, but for code with tight performance requirements no always.

>And you certainly won't want to implement Javascript in Javascript.

Oh I don't know, it could be an interesting project if only for an exercise in intellectual onanism!

In fact I've heard of it being done a few times. The first ones that pop up in Google are http://sns.cs.princeton.edu/2012/04/javascript-in-javascript... which is aimed at sand-boxing (and looks like an interesting if not efficient idea) and https://github.com/mozilla/narcissus/ which has the stated goal of being used for experimentation with the language itself (so the fact it is implemented in javascript is probably less relevant).