Lisp in Small Pieces: Table of Contents and Code
pagesperso-systeme.lip6.fr
pagesperso-systeme.lip6.fr
Also, Lithp from fogus http://fogus.me/fun/lithp/ is a nice and brief exploration of implementing Lisp in Python and good example of literate programming.
from I. Piumarta (Inria, VPRI), sophisticated yet beautiful C code.
I write Clojure code, read Lisp books, articles etc.
But I don't feel 'magic' yet.
How did you get 'addicted' to Lisps?
A programming language is a tool like any other and it is not magical or addictive. Your goal should be to solve problems by using the most appropriate tools for the job. Focusing on anything else I think is misguided.
Same applies - imo - to programming languages. I use Ruby for most of my work since "it just gets the job done"; but I really love the moments I can work on one of my clojure projects.
Clojure is my favorite hammer at this moment, that might change to F#, Haskell, Go, <new language> anytime.
I don't disagree with you - on the contrary - but just wanted to point out that fun might be a great motivator for chosing a language.
I have never used a language a fraction as fun as Scheme (except for Common Lisp, which is also quite fun).
If you try any of these exercises in a only procedural language (C, Ada, Pascal, Fortran, ...), you should feel how unnatural it is compared to lisp.
You really have to think about what it was like in 1990 to understand the appeal of Lisp. No Python, Ruby, Scala, C# or Java. First-class functions were not considered an important part of a language. Garbage collection was widely considered to be something to be avoided in a real language. C++ (this was long before even C++98) was a cutting-edge language.
You will not experience elegance on the level of Scheme from any of the languages you list: not Python, not Ruby, not Scala, C# or Java. I would argue that even Clojure and Common Lisp are not nearly as elegant (though they come closer than the rest).
On the other hand, I think that each language has its strengths, and things that it does more easily or optimally than most others.
Learning to program in different paradigms (procedural, OO, logical, concatenative, etc) can really be a mind-opening expericence, and it's one of the reasons that I most value learning the Lisp way. But other ways are also well worth learning.
Doing that will require you to deal with the AST of expressions you are parsing. Then, you can try to tweak a bit the evaluator to optimize it. Doing so will make you manipulate AST, and since LISP is his own AST, you become aware of what you can do with it.
I'm on my third read of it. The first time I tried to implement all the exercises in Ruby and failed around chapter 7 when the language ran out of expressive power. The second time round I implemented it in Javascript and got to chapter 9 before the syntax became too much of an obstruction to seeing what the code was doing (the good parts of Javascript are actually quite similar to Scheme in some ways but the syntax is just horrible).
This third time round I am implementing it in the language it was actually written in, Scheme. And having tried it with two other languages I can suddenly see why LISP is so suited for certain types of problems.
My 'magic moment' came when I finally grokked how the Y combinator works. It was like since I started learning how to code 4 years ago I had been continuously trying and failing to get two mirrors to line up perfectly so the images went off into infinity, and suddenly I got it just right and caught a glimpse of the wonderful self-referential simplicity of the entire of computation.
I use Ruby in my daily work but I want to start using more Clojure. There is a mathematical purity to LISP that other languages don't have.
It's like the whole language itself IS the fixed point function for humans interacting with computers.
A couple examples of some really great macros are those in PAIP[0]. In particular, look at the defrule macro[1][2] for a version of mycin[3]. The macro defrule is a DSL for creating rules about how to diagnose different bacteria. Also look at the rule macro[4][5] for defining DCGs[6], a way to parse natural language.
A great way to learn more about macros is through reading On Lisp[7], in which Paul Graham explores some of the really crazy things that are possible with macros, including implementing continuations[8], creating a DSL for ATNs[9] (another way to parse natural language), and even implementing an object system.
[0] http://norvig.com/paip.html
[1] http://norvig.com/paip/mycin-r.lisp
[2] http://norvig.com/paip/mycin.lisp
[3] http://en.wikipedia.org/wiki/Mycin
[4] http://norvig.com/paip/grammar.lisp
[5] http://norvig.com/paip/unifgram.lisp
[6] http://en.wikipedia.org/wiki/Definite_clause_grammar
[7] http://www.paulgraham.com/onlisp.html
[8] http://en.wikipedia.org/wiki/Continuation
[9] http://en.wikipedia.org/wiki/Augmented_transition_network
That's not exactly true. There are many languages, both old and new, which provide macro systems comparable to defmacro and/or syntax-rules. Dylan, Nimrod, Julia and Elixir come to mind.
I personally don't think there's one feature which makes lisps this great. It's really the whole experience, from syntax to repls to tools and so on.
(The "basically" caveat above is because some Lisps honor this code-is-a-list principle more than others. E.g., I have seen remarks about how modern Schemes have moved away from it at least a little bit, with syntax which is importantly not quite a list, though I don't know any of the details. And CL has other kinds of reader magic --- like one-character "reader macros" and like the implicit package which is used as a default for symbols at read time when no explicit package is given --- that can in principle complicate the obvious 1-1 correspondence between source and parsed-as-list representation, although in practice that magic is very seldom used in such a way that you need to think about it.)
http://www.winestockwebdesign.com/Essays/Lisp_Curse.html
However I wouldn't call it "curse" but merely the truth that Lisp programmers need a lot of self discipline to write maintainable code.
Lisp was one of the first languages I learned at university (also Pascal and Ada). Afterwards I learned almost every other new programming language. Lisp and the Scheme dialects are still the most powerful languages of all, to this day.
People who are intimidated by such a raw power should take a look at Nim (nim-lang.org). It takes the best of several modern languages and it also has an amazingly convenient and powerful macro system. For instance:
template repeat * (body: stmt): stmt {.immediate.} =
block:
while (true):
body
template until * (cond: expr): stmt {.immediate.} =
block:
if cond:
break
var i=0
repeat:
echo i
i += 1
until i==7I have never "switched back" to the likes of Scala or Haskell so I can't speak for those. ML and its brethren have been long on my list of languages to check out and only recently I started playing with Haskell.
For what it is worth, his articles about Lisp are among the things that got me interested in Lisp, and I still like Lisp.
I have this book. I've also worked on many Scheme systems and the internals of CMUCL. I was once a Lisp weenie.
The things that made Lisp special are not so special today. Basic things like garbage collection or dynamic typing exist everywhere. The more esoteric things, like CLOS, are esoteric for a reason (they are very difficult to use and impossible to master). The one feature that people still hype has always been a double-edged sword: macros. Scheme entirely ran away from the macros that Common Lisp has, and for good reason. But Scheme still has not developed a hygienic replacement that is equally powerful (and easy to use). They never will. It's been decades now.
The problem with macros and pet DSLs is that the best advice for using them is: don't. They can subtly alter the semantics of your code, and they conflate run-time vs compile-time. Not many people can elegantly weave through all these dimensions at once and not make a disaster. Homoiconicity has been oversold. The practice of CONSing everywhere is just awful, and slow. It's not the '80s anymore. CONS doesn't make sense today.
When you have first-class functions, closures and GC, you have the best things from Scheme/Lisp.
I know this is a long stretch, but if any of you bought a used copy of LiSP from someone in Virginia, USA, please can you check if your copy has a telephone number hand written on inside of the right cover? It's the only contact I had to my step-father and I have not heard from him since. We haven't been in touch since my mother's passing.
edit Google helped me find the front matter: http://assets.cambridge.org/97805215/45662/frontmatter/97805...