netbioserror
Homoiconicity wins in my book. Clojure is the best proof I have of this: What mattered was not the linked list or the cons cell. What mattered was that all code was just nested calls to functions and macros with the SAME general form: (function arg1 arg2 arg3 ...)

Expression-based programming using this core form is trivially easy, and makes immutable data structures downright pleasurable to work with. It also makes code generation easy, though I've never taken full advantage of it; even so, a DSL made of runtime functions is not only possible, but a natural extension of anything you're already doing. Backing those homoiconic expression forms with typical high-performance data structures like arrays and hash maps, as Clojure and Janet do, is a winning formula for making complex tasks simple.

All the patterns of yesteryear for modeling problems begin to look quaint when your program eventually just becomes a pyramid of expression calls, with `main` at the top and database hits at the bottom. The organization of the stuff in between really just becomes a question of standardizing function signatures and organizing modules so humans can easily navigate them.

ggm
It’s also worth noting that code generation (and therefore metaprogramming itself) are also not fundamentally innovations of Lisp. For example, in C++, it is entirely possible to link your application to libclang and build Clang ASTs inside your application C++ code, and use the Clang compiler to emit and run that code.

Ahem: can we discuss the word innovations and fundamentally above, and put two facts on the table:

LISP: 1959 C++: 1979

If they'd said "is not unique" I could agree. The innovation is a statement of origination. C++ did not originate this concept into a language system from 19 years prior to C++

neilv
To anyone not already experienced with Lisps, there's varying schools of thought and opinions on what's important and valuable, within Common Lisp (CL), and within the broader Lisp family.

For example, although this writer doesn't think macros are important, the Scheme (and especially Racket) branch of Lisp ran with macros, then with various other DSL support that take macros further (like Racket `#lang`). Racket also moved towards a strict definition of phases, and a very nice module system that works with that.

That might horrify some CL people, because it moves further away from the dynamic REPL live manipulation strength of CL, but others of us have found the tradeoffs very practical for our needs.

narag
...code generation (and therefore metaprogramming itself) are also not fundamentally innovations of Lisp. For example, in C++...

Wait, what?

Maybe I'm confused but doesn't innovation mean doing something not done before?

C++ and even C are more recent than Lisp, they can't be used as counterexamples. Or am I missing something?

(Edit> other than that, I forgot to say: nice article.)

jacknews
I just started learning Janet, and one of the things I really like is being able to use '-' in variable names. I didn't realize how much friction snake-case or camel case, ie having to use shift in var names, generate. It's a small thing, but a thing that differentiates lisps and algols.
Max_Limelihood
This is a really good explanation of why I find Julia (effectively a Lisp in terms of these features) to be indispensable. The ability to generate code on the fly makes life so much easier that I just can't live without it.
jjtheblunt
https://a.co/d/6NaRjQG

The "condition system" is niftier than i've seen elsewhere.

agumonkey
- ~no syntax

- induction

- induction

- some taste for minimalism (although CL/CLOS might feel different back in the days)

- human exploration oriented (repl, mop/updates)

- open homoiconicity, as a programmer lisp is an open box, makes you grow more in depth

- understanding of high and low levels in one place

- radical taste for innovation.. do whatever, you're near free

pfdietz
Lisp was a very early, if not the first, case of a language where types are associated with values, not variables. The evolution of implementations of Lisps showed that such languages could be implemented efficiently, even on stock hardware. This last realization took a while (witness how lisp machines were being developed into the 1980s.)
CalChris
No, Lisp did not invent if statements. They're in Fortran's 1956 Programmer's Reference Manual.

http://bitsavers.informatik.uni-stuttgart.de/pdf/ibm/704/704...

opportune
The third point is a little convoluted to me and doesn’t seem to be a beneficial innovation so much as a design choice.

Really for most of these benefits you can reductively boil them down to “code is data” because serialization-of-code, first class functions, REPLs, etc all more or less follow from that single major innovation.

This single innovation has more far reaching effects than many people realize as once people figured out that code-is-data and AST serialization means little pieces of code (not full programs) could be transmitted and executed over a network, it has enabled massive improvements in data processing through things like MapReduce and distributed databases.

adityaathalye
LISP gave us eval/apply, encoding all of computing in purely symbolic terms [1].

Consequently, we can manipulate a Lisp program as-is under almost any computing medium; as VMs for Turing machines and Quantum machines, as direct silicon hardware (Symbolics), under (paper-assisted) wetware (e.g. solve chapter 1 of SICP entirely by hand).

[1] https://www.gnu.org/software/mes/manual/html_node/LISP-as-Ma...

temporallobe
In Clojure, thread macros. Allows very terse but powerful operations on data structures in a very readable way that’s easier to reason about than nested calls in C -style languages.
drcode
didn't garbage collection originate with lisp?

if so, that should really be considered its most pervasive innovation

akkad33
Which Lisp is the most practical and easy to pick up for a programmer? I already tried emacs lisp but the experience of running emacs was not great, so I gave up
fsckboy
the innovation of lisp led to the innovations of scheme:

Lambda: The Ultimate Imperative

Lambda: The Ultimate Declarative

Lambda: The Ultimate GOTO (Procedure Call Implementations Considered Harmful)

https://research.scheme.org/lambda-papers/

jonjacky
Here are John McCarthy's own answers to this question, from 1980, about 20 years after he invented Lisp:

The Survival of LISP http://www-formal.stanford.edu/jmc/lisp20th/node2.html

He describes 15 innovations -- it is impressive that these were all innovations when he invented Lisp. He adds, "Of course, the above doesn't mention features that LISP has in common with most programming languages".

nathants
solving frontend dev in a permanent way.

https://reagent-project.github.io/

chromoblob
Any language where you can define the type for its own AST is homoiconic, isn't it? So what is the big deal?
smegsicle
notably not 'lisp features that have been absorbed elsewhere' but instead the opposite, lisp features that still make it unique

tl;dr

1. no part of the system off limits

2. pervasive interactivity

3. homoiconicity

baq
YAML.
AtNightWeCode
Useless parentheses?
sbjs
Everything worthwhile about Lisp has been integrated into TypeScript and JavaScript.
sr.ht