Common Lisp is great because it realizes that abstraction and expressiveness are what make fp powerful, and is smart enough to know when to drop 'purity' in favor of these.
After spending a lot of time with Haskell and Scheme, Common Lisp feels very non-functional, however I still feel it is the best language for expressiveness and abstraction. Work with Scheme and Haskell enough and you'll find yourself writing some convoluted things to maintain purity. The problem with purity is that while it makes somethings much easier to express, there are times when you have to stop and ask "how do I express this", I find common lisp always gives you some way to express anything, but leaves you asking "how can I express this better?"
I don't think you can lump all the Scheme languages into one umbrella and more importantly lump Scheme and Haskell in that context.
For example, Racket has really good constructs that lets me "drop 'purity'", control side-effects, build sequences, control the flow, build classes, manage complexity while at the same time giving me the power to build higher levels of abstractions, express my thoughts and reason with my program.
0. Racket Guide: http://docs.racket-lang.org/guide/index.html
1. System Programming with Racket : http://docs.racket-lang.org/more/
"Racket is still a dialect of Lisp and a descendant of Scheme. The tools developed by PLT will continue to support R5RS, R6RS, the old mzscheme environment, Typed Scheme, and more. At the same time, instead of having to say “PLT's main variant of Scheme,” programmers can now simply say “Racket” to refer to the specific descendant of Scheme that powers PLT's languages and libraries."
Reference : http://racket-lang.org/new-name.html
>There seems to be a great deal of interest
>from the functional programming community
>in benchmarking. Is there enough interest
>to create a new computer language shootout
>that showcases more relevant/suitable tasks
Does this sell books? Should I write one?
Other than that, this writeup reflects what I've learned so far of Common Lisp - it's much more of an imperative style language than it is a functional language.
I use Clojure's looping constructs and list comprehensions for most of the tasks; explicit TCO using loop/recur for problems which are best expressed recursively.
In true TCO, you optimize not only tail calls to the same function, but also tail calls to other functions. (Think of coroutines as an application).
One way to think of a TCO is that you are turning a function call (machine code to save your spot in the function, then a jump) into a simple jump (you don't need to save your spot, because there is nothing left in the function anyway).
Clojure doesn't support this (because it would be too difficult[inefficient, i think kawa scheme and JRuby do implement it] on the JVM). I assume that the common lisps which do support TCO, have true TCO, as they are using assembly or interpreters.
Clojure's TCO can be seen as a special form of a loop (in fact, it is very easy to write a macro that takes a loop-recur form and transforms it into a common lisp style Do* loop).
This chunking is for efficiency, but it has the (sometimes) weird implication that you ask for the first element in a sequence and it evaluates that first element, and the next 31 elements as well. This is troublesome if you attempt to use side effects.
(Mr. Fogus has a nice writeup (and workaround) of this phenomena here: http://blog.fogus.me/2010/01/22/de-chunkifying-sequences-in-...)
I have to admit, I am not quite getting my head around how using a lazy sequence to the same effect would work (ignoring the chunking issue). I see how they are similar, a lazy sequence is just a flattened trampoline. Could you maybe pastebin or lisppaste an example?
Anyway, I guess the point I was trying to make was not that it is impossible to do these things, but that TCO is a compiler level optimization of the function calling convention (manipulating the stack), and although Clojure has 'tail calls,' it can't really be called TCO in the true sense of the word. (Which is OK, as you said, there are other ways to do this sort of stuff).
"secretly Scheme with bad syntax"
It's a comp.lang.lisp post by Kent Pitman. Here's the header:
From: Kent M Pitman <pit...@nhplace.com>
Date: 15 Jul 2007 02:19:09 -0400
Local: Sun, Jul 15 2007 1:19 am
Subject: Re: New Computer Language Shootout?