Many years ago, Paul Graham wrote an interesting essay called “What Made Lisp Different” in which Graham details the 10 or so language features that differentiated Lisp from any other language. This was my first introduction to Lisp and the way Graham made it sound, Lisp invented most of the modern features we associate with programming languages, like if/else loops and garbage collection. What’s astounding to me is that Lisp is an incredibly old language, first created by John McCarthy in the 1960s and many, if not most, of the language features have been integrated into modern languages.
Lisp has attracted a small but vocal and dedicated following over the years, somewhat leading to the derisive moniker “lisp weenie” for the entrenched few engaging in programming language holy wars. However, recently it seems as though Lisp as it has been understood has been mined of its useful features and ideas. I’m not the only one saying this - Peter Norvig, Research Director at Google and author of Paradigms of AI Programming (one of many highly esteemed computer science books written in Lisp) said “[Python] is an acceptable Lisp.” And indeed, most of modern AI development has moved from the default language of Lisp to Python. It’s unthinkable to begin any model without reaching for Numpy, Pandas, PyTorch, Keras, or some other ML framework or library, all of which are Python tools.
I think the future has finally caught up to Lisp and it’s time to create the next 50 years of language ideas to slowly trickle into the mainstream. What might this language be like? What features would it have? What applications might this language be suited for? This blog series is an attempt to both answer and build that language. It’s somewhat ambitious, nothing ventured, nothing gained, right?
Philip Greenspun’s Tenth Rule of Programming states: “Any sufficiently complicated C or C++ program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.” It’s funny because it’s true, and a little biting because it’s also true of Java, Python, and whatever language you’re currently most attached to. Programmers keep reinventing Lisp’s core ideas because those ideas are genuinely useful and keep getting rediscovered by people who didn’t know they were reinventing them.
The plan here is to run Greenspun’s Rule in reverse. Start with the poorly-implemented Lisp — on purpose — and use it as the substrate to grow something genuinely new. That Lisp is called Schematic, and it is not the goal. It’s the foundation. This also explains why certain features like content addressing go in early, before the language can even do anything interesting: if GRASP’s promise is that program transformations are auditable and reversible, you have to build that into the foundation rather than retrofit it later.
So my proposal for how this language would work is as follows:
Graphs as a first class data structure - Lisp stands for list processing because the nature of the language is that it is composed entirely of lists. The supremacy of lists leads to several interesting properties like homoiconicity, macros, and easy construction of domain specific languages. But why choose lists specifically? Why not arrays or stacks or queues? Indeed, several other languages have asked this question and led to interesting results almost on par with Lisp. Chuck Moore’s Forth, for example, is a stack based language. Kenneth Iverson’s APL stands for Array Processing Language (similar to Lisp) and is infamously known as a write only language for its dense notation. Still, these seem like arbitrary selections. I believe the language of the future should base its data structure on the graph.
Why? Because every other data structure can be modeled as a limitation or mutation of a graph. A list is simply a graph where one node connects to one that precedes it (if at all) and one that follows it, at maximum. A graph can be represented as an array, via the adjacency matrix. A graph can be modeled as a list with graph rules dictating how it can be modified leading to a stack or heap. It would make sense to call such a language Grasp - a graph processing language.
This gets deeper though, when you consider the impacts of homoiconicity with graphs. If list homoiconicity can allow for expressive DSLs, a graph homoiconicity will give you languages like Lisp, Forth and APL as domain specific languages. And you can make further DSLs in Lisp-as-a-DSL! In Lisp, DSLs are possible because the language itself is the abstract syntax tree. In this hypothetical Grasp, if homoiconicity with lists gives you Lisp’s power, homoiconicity with graphs should give you more. Programs ARE graphs — the control flow of a concurrent system, the dependency graph of a distributed computation, the message-passing topology of a microservice architecture. These are all graphs that programmers currently draw on whiteboards and encode awkwardly in callbacks, futures, and channels. Making that topology explicit in syntax is the graph equivalent of what Lisp did with lists.
Content Addressing - if you’re a developer, one of the first things you do when starting a project is version control your development in some way. Modern tooling generally uses git and something like github or bitbucket. While there is an argument to be made as to why this should remain outside the language for external file management, I’ve always wondered, why doesn’t such a common utility come built in to the language? After all, under the hood git is a merkle tree and merkle trees are suspiciously close to ASTs. Fun fact: merklized abstract syntax trees do exist. Instead of version controlling at the file level, we would be able to version control at a semantic, function or macro level.
Content addressing, tagging nodes of our graph with a hash, would also have a very very powerful side effect besides enabling granular version control - it would make macros and graph transformations safe. Or at the very least, reversible. One common criticism of macros is that they are, essentially, too powerful. It’s incredibly easy to create a write only DSL that only your lone Lisp wizard understands. While content addressing can’t solve every issue, it can offer a new developer some insight into the history and evolution of a macro. Macro expansion produces a new AST. The pre-expansion AST and post-expansion AST each get their own Merkle roots. The expansion relationship is stored explicitly — you can diff what you wrote against what the macro produced, and you can trace any subexpression in the expanded output back to the macro template that generated it. Content addressing makes macro expansion auditable; Merkle structure makes it efficiently navigable.
Another somewhat interesting output of this content addressing idea is that a really tight package registry becomes possible. This is a bit beyond just PyPI and offers a few potential benefits. One is that dependency hell becomes a different hell of matching hashes instead of “some-package@1.2.3.” But at the end of March 2026, in the wake of the LiteLLM attack, this offers a potential defense against supply chain attacks.
Petri Nets - One very natural outgrowth of a graph based programming language is that it’s very easy to represent graphs (duh-doy). The obvious thought is that representing neural networks would be incredibly easy in this language, and that’s true. But there’s a far less obvious but more consequential application called Petri nets.
Petri Nets are a model for concurrency that have the distinct property of easily being represented as formal methods specifications. What this means is that Petri nets are exceptional at modeling distributed systems and furthermore checking whether they’re actually valid. This is much deeper than it appears, because a whole class of subtle but dangerous bugs exist where programs are required to run in parallel and on multiple computers — the modern computing environment.
Petri nets are essentially a type of graph, so if the Grasp interpreter is a Petri net under the hood, you get a few nice things for free. One is you get a formal specification. Developers historically have been resistant to adopting formal methods because, why write a specification when you can just write the software? But with Grasp, writing the program is writing the specification. Which means all you need to do is automatically run a model check as part of your debugging process and you get formal verification with no extra work. This would be a great boon for anyone developing distributed or concurrent software. You would be able to catch all sorts of bugs — like deadlock, where two processes wait on each other forever — that previously have been deemed too time consuming to chase in development and debilitating when they hit in production.
The intersection of these three things hints at several properties that would be desirable for a language of the future. In particular, any language developer in 2026 needs to design for adoption by an LLM. The interplay between formal methods, content addressed tractability, and the graph data structure is perfect for LLMs primarily because the core issue (at least as of March 2026) is how easily LLMs generate insecure and vulnerable software. The qualities of this language mitigate many of these issues but also facilitate code management and context window management for LLMs. It may be that in the future these will no longer be concerns, but as of now, mitigating these concerns in the infrastructure layer can also enforce the generation of software that is secure and has minimal vulnerabilities.
This also leads into the motivation behind this blog. Besides popularizing the Grasp programming paradigm, this blog will attempt to show how LLM assisted development actually works. There’s no doubt AI has changed programming, but all coverage tends to oscillate between the two extremes of “I ran this on Ralph Wiggum mode for 3 seconds and got a perfect app that generates $1239082427874 per hour!” and anti-clanker, luddite, “They took our jerbs!” coverage. I’d like to show a more honest integration of AI into software development, to show how AI can enable projects that previously would have been beyond my technical ability, but at the same notion still requires human-assisted guidance and taste to fully realize. I think making one-shotted SaaS apps isn’t a terrible use but to limit software development to just “applications” ignores the history and tooling several geniuses before us had to figure out to get to this point. There’s still a lot of, maybe not low-hanging fruit, but mid hanging fruit to gather.
So this is that grand dream - a graph programming language that offers maximum flexibility with built in security and validation. Will this work? Is it possible to create a programming language for the next one hundred years? Is there still a future for programming languages at all? Or am I being too ambitious?
We’ll find out together.
