I prefer Common Lisp, for a variety of reasons (mostly practical ones). Scheme can technically do the same things as Common Lisp, but you'll have to reinvent a lot of wheels in R5RS to get the same functionality (wheels which have been reinvented by serious Scheme implementations, but unlike CL's these features are not all portable across many other implementations. Implementing some CL features in Scheme may require you to hack the underlying implementation or make your own implementation as they're just too extensive). R6RS Scheme does move more closely to what CL offers, and the base library and macro support is more extensive.
What Scheme has that Common Lisp doesn't? Full continuation support(call/cc) and proper hygienic macro support and guranteed TCO.
In practice, all real CL implementations do support TCO, however you tend to have the freedom of turning it on and off, depending on your needs, and there are some CL features which don't play that nicely with TCO (optional dynamic scope, which implies one needs to use a variable value stack and have support for unwinding that stack automatically), TCO is just considered an optimization, which is why it wasn't included in the standard as mandatory (TCO is actually much more, if you think about it yourself, or cheat by reading the lambda papers, for example, TCO can be used as the ultimate goto, without most of the issues associated with goto...).
As for
call/cc, it doesn't play too well with
unwind-protect and it again forces too many choices on implementors (like forced TCO). It's supported by 3rd party libraries which are also mostly portable, but it usually requires a code walker, as it's done by performing CPS transforms (some implementations also support the low-level version of dumping heap/stack and restoring it).
As for hygienic macro systems, I'm not a huge fan of them myself, they force hygiene on your macros, while restricting some of your power. Common Lisp provides enough tools to let you achieve hygiene(
gensym, make-symbol, packages,...), however the responsibility lies on the programmer to know what he's doing (just like any other kind of programming...). Scheme's complex hygienic macro systems do make writing some types of macros easier, while others a huge pain, CL's low-level macro system is probably one of the simplest in existence, and it works as a compiler hook which just calls your macro expander, which destructures the arguments(if you wish), and then you can use any real Lisp code to generate the expanded form. Note: you can implement hygienic macros in Common Lisp, protably, however almost no CLer is interested in doing it as they're fairly content with
defmacro(there are a handful of toy implementations which show how to do it, if you're curious).
Now the main difference between Scheme and Common Lisp(besides Scheme trying to be minimal yet beautiful and Common Lisp attempting to be complete and power), is that Scheme has a one-namespace philosophy, while Common Lisp, has a 2-n+ namespace philosophy. The main consequence is that in CL, a symbol has a normal value and a functional value/slot, while in Scheme, a symbol has only a value, and defining a function, results in binding the symbol to that value in the lexical scope of that form, while in CL, you can use the same symbol to name both a variable and a function, without causing conflicts. This allows more robust low-level macro writing, as well as having arguments/variables of the same name as the function (for example, you can have a function that has an argument named 'list', that works fine in CL, but in Scheme, you'll see people name it 'lst','lyst' or whatever, to avoid shadowing the
list function). The CL 2 namespace way is called Lisp-2, and the Scheme one is called Lisp-1. I favor Lisp-2 strongly, but I can see why others like Lisp-1. The disadvantage of Lisp-2 is that it makes writing some types of functional code a bit more verbose(the #' reader macro, or
(function ...) special-operator being required when referring to a function by symbol name, when the symbol isn't in the
CAR position, as well as having to use
funcall to call variables having functional values). Read
http://www.nhplace.com/kent/Papers/Technical-Issues.html for more details.
Common Lisp also allows optional declarations, which allow you to give hints to the compiler allowing better optimizations. Some CL compilers generate pretty fast code (like SBCL, who can also infer types to some degree), and are well-known for their speed.
Personally, I learned Scheme by reading my SICP first, and then moved to Common Lisp for most of my real-world programming needs. If you choose to learn CL, I'd recommend looking at Practical Common Lisp, maybe look at PG's ANSI CL, PAIP, AMOP, and of course have the Hyperspec and ClTl2 as referneces.
There's also quite a few notable Scheme books, my favorites besides SICP would be Lisp in Small Pieces(compiler/interpreter building) and the Lambda papers.
Or did you just choose one as your way of saying, “I've read SICP”?
I found that CL gives me a huge amount of freedom when writing code, like none other that I've encountered before. This was the main reason that I even learned Lisp - I was being pissed that the language that I was coding in was restricting me in very silly ways and I had to write a lot of boilerplate (it was Java/C#, but at that time I knew C, ML, some x86 asm and some others). Currently, I'm using CL for the majority of my high-level programming needs and C (sometimes with some asm) for mostly low-level needs.