The German school of Lisp is described by Kazimir Majorinc as a Spartan movement1 in Lisp implementation. But let me be clear, the Lisps in question are not toys like the one’s littering the Lisp landscape (including my own). Likewise, these Lisps are not libraries nor are they full-blown development ecosystems.
Let’s explore these distinctions for just a moment to clarify my meaning.
This post deals with that crimson space between, but first…
Exo-Lisps are the variants that exist to serve very pointed use cases. They can take the form of highly specialized libraries or embeddables like GLOS or Lush. Likewise, Exo-Lisps may facilitate embedding within applications or act as extension frameworks like Guile, Visual Lisp, Elk, and Emacs Lisp. Finally, Exo-Lisps like LFE and Liskell serve as skins over the semantics of another language.
Practicality is a relative term. Having said that, there are clearly a set of Lisps that exist primarily to solve “real world” problems, including: Common Lisp, Clojure, Scheme (R5RS, R6RS, R7RS-big), Racket, Chicken Scheme, and Dylan. I’m tempting libel cases by including this particular category and filling it with these particular choices, but so be it.
I struggled to find a way of separating Exo-Lisps and Kernel Lisps and the following distinction from this struggle arose. Where Exo-Lisps serve as a framework for a specific problem, Kernel Lisps serve as a framework for a more general problem — language development and experimentation. Perhaps I’m splitting hairs. Some examples of Kernel Lisps include: R7RS-small, Scheme48, Lisp Machine Lisp, EuLisp, and Kawa.
As I alluded to earlier, the Lisp landscape is rife with toys, Ur-Lisps, and half implementations. However, the vast majority of these Lisps exist for pedagogical pursuits and are rarely (if ever) overtly practical2.
Fluchtpunkt Lisps skirt the vanishing point between theory, practicality, and art. These implementations are all of the other categories in some way, while simultaneously being none in particular. They may or may not be general purpose languages in all instances, but they are all driven by a fervent ideal.
Below is a list of Fluchtpunkt Lisp implementations that I’ve found, and some discussion of their driving ideal (as I understand):
T is my favorite Scheme variant and the inspiration for many a Lisp thereafter. I’ve poured over Stephen Slade’s T book numerous times, finding something mind blowing each time. The primary driving force behind T was to prove that a Scheme could be made to run extremely fast, and fast it ran. T’s compiler technology was the motivation for numerous dissertations, and remains influential in many ways, even if some of its compilation techniques have fallen out of fashion.
Qi (and its successor Shen) really push the limits of what we might call a Fluchtpunkt Lisp. I suspect it requires a categorization of its own.
A few years ago I was looking for a Lisp to dive into and my searching uncovered two extremely interesting options: Clojure and Qi. I eventually went with Clojure, but in the intervening time I’ve managed to spend quality time with Qi and I love what I’ve seen so far. Qi’s confluence of features, including an optional type system (actually, its type system might be more accurately classified as “skinnable”), pattern matching,3 and an embedded logic engine based on Prolog, make it a very compelling choice indeed.
newLISP raised some ire at one point or another because of its design choices, specifically its choice of pervasive dynamic scope and fexprs (pdf).4 I like dynamic scope under some circumstances, but I can’t say that I’ve followed it to its logical end for any application of significant size or complexity. The advocates of newLISP are interesting folk and in many ways of my own mind. For example, how would one calculate Pi out to
n digits in newLISP?
(define (pi n) (replace "\\" (join (exec (format "echo 'scale=%d; 4 * a(1)' | bc -ql" n))) "")) (pi 30) ;=> "3.1415926535897932384626433832795028841968"
Why you would call out to the UNIX
bc command of course. Why would you need your programming language to provide that type of calculation5 when there are more appropriate tools for doing so? I suppose the fundamental philosophy of newLISP is to not necessarily provide everything, but to make everything possible. newLISP facilitates possibility by treating the use of
eval as a first-class approach and utterly idiomatic.
I agonized over including Paul Graham’s Arc in the category of Fluchtpunkt Lisp, but I think this is the correct place for it. The driving forces behind Arc are succinctness and centenarianism — both of which are certainly emblematic of the Fluchtpunkt ideal. Arc hasn’t taken off as much as non-Paul-Graham humans would have liked, but I believe that the root of the problem is that they prayed for Practical, but instead got Fluchtpunkt.
I first came across Pico Lisp when reading the paper “Pico Lisp: A Radical Approach to Application Development” by Alexander Burger and was instantly fascinated. The primary goal is to provide an idealized Lisp interpreter that runs as fast as possible. To accomplish this goal Pico Lisp limits its feature set and optimizes the code path along the dimensions of its features. The core types provided by Pico Lisp are numbers, symbols, and lists. Given the paucity of these types Pico Lisp has the advantage of always taking the most direct interpretation path and thus avoiding any unnecessary checks and abstractions that a more corpulent Lisp might require. For example, Pico Lisp’s
quote function is defined in such a way that it returns all of its arguments unevaluated allowing the operation of
quote to optimize into only a return of its
cdr rather than the
car of its
cdr. Simple no?
Pico Lisp is, in my opinion, the most interesting entry in a family of really really small Lisps that also includes Nanolisp and femtoLisp, although I would hesitate to include these latter two in the Fluchtpunkt category.
Wasp Lisp is a small Scheme inspired by Erlang with lightweight cooperative threads, communication via channels, and an implementation of MOSREF. This latter feature is fairly interesting in that it allows one to create a network of “drone” Wasp VMs that can receive secure snippets of code from a remote console for execution.
What is Fluchtpunkt?
Fluchtpunkt Lisps are…
- Focused: Uncompromising in their vision
- Spartan: Devoid of the seemingly unnecessary comforts found in many modern languages
- Controversial: Not always by design, but often because of their design
I intentionally avoid the word “minimal” in this post. Spartan is Mr. Majorinc’s word, and I think it is more appropriate. ↩
However, toy and Ur-Lisps are practical insomuch as the act of implementing them is good programming practice. ↩
I miss pattern matching.
clojure.core.match, wherefore art thou? ↩
Regardless of the chances of bringing a libel suit on myself, I will say that fexprs are effectively runtime macros. ↩
Well, you could also use
(mul 4 (atan 1))if you didn’t care about precision. :p ↩