The main insight for me from this exercise is LISP wasn't always as beautiful as it is nowadays, it "grew prettier over time".
As others have already remarked here, since about the 1980s, there appears to be an increased level of nameing, consistency and better indentation, all contributing to an overall increased level of "prettiness".
The core concepts were already there, of course, and that's timeless beauty.
I'd agree that "beauty of syntax" is relative and subjective. It's a fascinating observation that Lisp grew prettier over the years.
But the philosophical or mathematical beauty of the core concepts of Lisp, I feel like they're closer to eternal and objective beauty, if there is such a thing. It's like they're low-level universal primitives, not only of human thought but thought itself. If we're to ever communicate with an extraterrestrial intelligence, they would probably grok Lisp.
Dunno if I'm in the minority, but I just can't warm to [], either in lieu of or augmenting, () in SEXPRs. Just never felt they were necessary and, if anything, I find them distracting. Likely because I'm not used to them (baby duck syndrome and all), but the regularity of Lisp syntax, to me, is a boon, and the [] just mess that up for me.
Reader macros/literals allow for explicitly differentiating between built-in data types, and provide semantic meaning to otherwise indistinguishable forms. For example, defining a function:
In Racket, you write `(define (foo arg1 arg2) (+ arg1 arg2))`. Why isn’t `(foo arg1 arg2)` evaluated as a function? It’s a list and it isn’t quoted, so it should be evaluated. However, `define` is a macro (I think, might be a special form), so that list isn’t evaluated and doesn’t have to be quoted. That violates the basic tenant of “unquoted forms wrapped in a list are evaluated as fiction calls.”
In Clojure, you write `(defn foo [arg1 arg1] (+ arg1 arg2))`. The [] is a reader macro, a vector literal. It communicates that it’s not a function call but simply data (in this case, a vector containing two symbols).
Maybe I’m just used to it but I find this stuff really helpful.
I would agree more with this view if there was also an explicit indicator for lazyness: in (define (foo arg1 arg2) (+ arg1 arg2)) the two parts (foo arg1 arg2) and (+ arg1 arg2) are both interpreted specially; the former as a data structure and the latter as code with delayed execution.
Using square brackets in place of some parens is something some of the Racket professors started doing. I assumed it was because they thought it would be helpful to teach high school students in http://htdp.org/ . I defer to them on teaching, but I think it looks ugly, is harder to type, and seems like it's more confusing in code examples (people thinking it's significant, when it's not).
One thing I did do is make an Emacs mode, https://www.neilvandyke.org/quack/ , in which typing square brackets instead inserts parentheses when appropriate. This is helpful on US keyboards, on which parens require a multi-key press but square brackets do not.
Yeah, in R6RS square brackets are considered to be perfectly interchangeable with regular parentheses. That decision was reversed for R7RS-small, though.
I find them very useful in the way Racket uses them, which is by convention only. In Racket, `[<expression>]` is identical to `(<expression>)`. But Racket uses them in a conventional sense, for example, in `let` bindings:
I'm not a lisper by any measure. I want to dabble at one point in Scheme and I got to do slightly more than take a look with some basic tutorials.
I find the example from Friedman the most readable by far. It is probably also the only one that is typeset with proportional fonts. A few of the superficial things about Lisps I am fond of are the kebab case and space delimitedness (same as shell, which also has some Lisp qualities afterall). They all come nicely with proportional fonts. However I do really prefer proportional fonts for code in general. Also operating with italics, bold is preferrable for me to color.
"Foo" has a long and deep history. There was a comic strip called Smokey Stover that started in 1935 whose title character was a "foo fighter" (firefighter) and drove a "foomobile" (a tiny fire truck with only two wheels). The author of the strip claims to have discovered the word "foo" when he saw it written on the bottom of a Chinese figurine, but I don't think that's the real etymology. I think "foo" was just short for "phooey", and was used to designate things deemed nonserious or trivial (somewhat similar to how "lol-" or "lulz-" is used in modern times).
Whatever the case, "foo" became associated with "bar" via WWII slang "FUBAR"; WWII also gave us "foo fighters" in the UFO sense. War is like the internet in that it brings together people of different backgrounds who otherwise might never interact, so it's not surprising that with things like foo, FUBAR, and Kilroy, WWII had something resembling a predecessor of modern meme culture. It entered hacker culture via the MIT TMRC culture in the 1950s. Their railroad layout had a "foo counter" which was a digital clock which would display the word instead of the time when certain scram switches were pressed. When MIT people began cultivating an interest in programming computers for its own sake, they brought "foo" with them and it spread into the greater hacker meme diaspora.
There's nothing quite as hacker-y as the word "foo", and the strong association with hacker culture goes back as long as hacker culture was a thing, and even before. It still reminds us to not take things so seriously, mess around, and have a little fun.
"foo" might have an association to the whistle from the steam engine era. I have a memory of the whistle in very early Disney animation. Also, I believe in Mandarin Chinese "foo" indicates the end of the sentence.
Structural editing is one of the amazing things you get for free in Lisps, but I cannot imagine how it could be done without parentheses. I also don’t really find it more readable without them, but it might just come down to what you’re used to. Alas, this is a nice experiment nonetheless.
This basically happens in my mind when looking at Lisp code. Parens are just handles that allow me to manipulate the expressions for structural editing.
This makes copy and paste between files or to/from a repl _really_ annoying. Splice a delimited sequence anywhere and auto-format is categorically better.
You couldn’t round trip Python through Apple Mail either.
To be clear, though Ruby’s massive popularity was entirely due to the advent of Rails.
Ruby is a fantastic language — Smalltalk object model with GC and a usable syntax! — but the English documentation was nonexistent or incomplete — even after the “Pragmatic Programmers” book massively increased the Ruby audience — and the core team was all Japanese, so there wasn’t ever much of a constituency for the core language outside of Japan.
The unfortunate thing is that Rails soured a lot of people on Ruby. (People don’t understand that a lot of what they encounter with Rails is dialect, not the thing itself. Ruby makes it easy to build dialects.)
this is an interesting collection. I am reminded that interactive systems ahead of their time like LISP and smalltalk were cursed with illegible font technology, which was very off-putting at the time, and it's only comparatively recently that they've improved.
Anyone have any recommendations (books, courses, videos, etc.) on learning LISP? I've been intrigued by it and want to integrate it into a game I'm building as a development tool but not sure where to start on learning the language.
For Common Lisp, there are several free books available:
- Practical Common Lisp (aimed at people who know how to program in a more mainstream language already) [1]
- Paradigms in Artificial Intelligence Programming (my personal favorite) [2]
- Common Lisp: A Gentle Introduction to Symbolic Computation (aimed at absolute beginners of programming) [3]
I highly recommend the r/lisp Reddit community. Reddit as a platform has its issues, but the Common Lisp community there is very responsive and very helpful.
Lastly, you might be interested in checking out Kandria [4], a game written entirely in Common Lisp, to be released imminently on Steam.
Along those lines there is a classic side scroller with mouse aiming called Abuse[1] that was written in Lisp. The source code is in the public domain now[2].
Is there a reason why some well-known Lisp hackers are Japanese? I noticed the devs of Kandria (radiance, etc.) as well as Fukamachi (woo, clack, mito, etc.), and am wondering what led to that kind of geographical distribution.
> Is there a reason why some well-known Lisp hackers are Japanese?
Perhaps, they trained in the 5th gen computing environment begun in 1982 by Japan's MITI (Ministry of International Trade and Industry).
"It aimed to create an "epoch-making computer" with supercomputer-like
performance and to provide a platform for future developments in
artificial intelligence."
Because it is a large country (Population = 124M) and it had already in the past a Lisp community.
Many years ago at an event I met people from a commercial Lisp vendor in California. They had also business cards in Japanese, because a bunch of customers came from there.
Especially today, since Lisp rather than being a single thing, is a family of languages. I mean, there's some truth to "JavaScript being a Lisp", so you can see that it's a bit open ended.
If you're looking for an embedded Lisp, then I would concentrate on finding one that simply appeals to you. That is, find one that integrates easily, or has a particular feature that you like, or any of many things that may catch your eye.
Once you pick one, then simply "learn that". Consider GIMP originally started by integrating SIOD (Scheme in One Defun), which is a simple Scheme interpreter. They have since moved on to TinyScheme (of which I'm unfamiliar).
But, SIOD has been around forever. SIOD begot SCM which begot GUILE, which is specifically designed to be embedded. It's also pretty large.
ECL, which stands for Embedded Common Lisp is, well, a Common Lisp. Scheme and Common Lisp are both Lisps, but quite different from each other.
That's why rather than saying "pick this", simply find one you like and learn that. The landscape is wide and rich.
I always recommend Make a Lisp [0]. It's a guided experience creating a Lisp in whatever language you already know. If you go through all the steps, you'll have created a self hosting Clojure-like Lisp.
For me implementing a Lisp piece by piece helped me better understand its core ideas.
MIT OpenCourseWare has 6.001, SICP. Watching the '80s videos was how I got started with Scheme. Though on the book front I would definitely recommend starting with Concrete Abstractions before SICP.
With Common Lisp I think the standard road is Gentle Introduction followed by Practical CL followed by PAIP.
Very interesting language, but so difficult to read. Something about the undifferentiated sea of lowercase letters just makes my eyes glaze over. People say it gets easier as you use it, but I never managed to get there.
Strange to me. The "modern" style (roughly mid 80s) is super clear to me, with the indentation doing a lot of work and the symbol names so clear (I still find the MixedCase jarring and significantly slower to parse, while using-dashes or even using_underscores much easier).
This style also encourages blocks to be compact so they almost fit right into your fovea. The spread-out "C" style that emphasizes the curly braces on their own line seems so backwards, emphasizing precisely the thing you don't care about.
> The spread-out "C" style that emphasizes the curly braces on their own line seems so backwards, emphasizing precisely the thing you don't care about.
Really? I like the curly braces on their own line precisely because that's what I do care about. I want to see the block structure - the context, if you will - before I think about the individual lines.
I think you are right. We should strive to keep the syntactic structure of the program separate from the actual symbols used in that structure. Then you can understand the structure separately from its "content".
The symbols are meaningless by themselves, except that the same symbol can be used in multiple places. BUT the syntactic structure of a program is NOT meaningless. It in fact defines the "meaning" of the program - in as far as the symbols used are arbitrary.
Therefore if you can express the program structure separately from the symbols, you make the program easier to comprehend.
I've seen too much over the years. I've seen indentations be a lie. I've seen indentations get mangled because someone's editor is set to use tabs instead of spaces, or vice versa. I can only halfway trust the indentation, but the curlies don't lie.
Yes, though the parens are important. In fact grinders (code formatters) are quite commonly used in Lisp, so the indentation is just instruction to the programmer; it has no semantic value to the interpreter or compiler.
Funny, because traditionally it was (ALL-UPPER-CASE)
Nowadays, indentation does a bunch of heavy lifting when it comes to readability. Modern Lisp-inspired languages (such as Clojure, but also some dialects of Scheme) also use other symbols in addition to parenthesis (like square brackets). Usually they are interchangeable, but I found that it can sometimes help.
I find it difficult to read LOOP macros. And some versions of LET. But they are bastions of readability if you compare with languages like_c<with<templates>>(T) and_macros(void);{}
In prose yes. However there is a structure to dialoge, that is hard to miss, you also have indentations, sections and chapters. Many books have lists for example, but it is usually not prose.
In some types of Lisp programming (such as Emacs lisp), it is common to use Form–Feed characters as chapter breaks within a file. Alas, some newer languages like Rust really don’t like that.
The first three from the McCarthy papers remind me of FRED, a Lisp-like language that was built into the office suite Framework -- but used @func(a,b,c) Lotus-style notation for function calls.
As others have already remarked here, since about the 1980s, there appears to be an increased level of nameing, consistency and better indentation, all contributing to an overall increased level of "prettiness".
The core concepts were already there, of course, and that's timeless beauty.