How to Write a Lisp Interpreter In Python (2010)
norvig.com
norvig.com
First, there's what I think is an important distinction of idiomatic programming in Scheme, for which the first example in the article gives the wrong idea, with a noble lie: that Java code implies an immediate return, but the Scheme code does not.
Were that Scheme expression not in a tail position of a procedure (which it probably wouldn't be), it wouldn't have effect analogous to that of the Java code. And a one-armed `if` makes little sense in a tail position in modern Scheme, and looks erroneous.
Scheme is a full imperative algorithmic language, and doesn't have to be used in a pure-functional way, but idiomatic programming in Scheme tends to lean towards functional when practical. You almost never do premature returns quite like that in Scheme, for example. (One can do most any memory-safe thing one wants, including the less-idiomatic and even the outrageously insane, but hopefully over time one learns the idiomatic ways, rather than overuses/misuses less-idiomatic features, like leaning on a crutch they don't need and that's actually harmful to them.)
Separate from that, another thing possibly misleading about this article is that their Scheme implementation doesn't do what's sometimes called "proper implementation of tail calls" (which would be required to be a real Scheme). Idiomatic Scheme will tend to use tail calls heavily, with impunity, which would not be the case if a Scheme implementation let such calls exhaust resources.
(Thanks, would edit if I could.)
Scheme already has undeserved image problems, from various CS101 drive-by exposures that students get to it, never properly learning it.
I started a project some time ago to write an elisp interpreter, mostly for fun. But since elisp is much more like Common Lisp than Scheme, it has a surprising amount more syntax than a Scheme does. The parser was much more complex than I initially thought it would be.
P.S. Of course, a Lisp-2 saves us only from an unlimited proliferation of parentheses, but a simple (defmacro foo () 'foo) will allow you to get a couple whenever really needed.
Related: https://news.ycombinator.com/item?id=20556927 :)
Particularly good is (canonical?) lisp-in-lisp code at the end.
It used to be writing a Lisp interpreter in Lisp.
> I think it meets Alan Kay's 1972 claim that you could define the "most powerful language in the world" in "a page of code." (However, I think Alan would disagree, because he would count the Python compiler as part of the code, putting me well over a page.)
If anyone is curious, I have some ideas on how you could more precisely define this problem and an objective mathematical way of evaluating it. Shoot me an email if curious.
Then I got stuck at recursively evaluating macros.
This is a great article.
>>> parse("(")
...
IndexError: list index out of rangeI used the same article to write lisp in C#.... worked out really nice