16 July 2023

In search of the Holy Grail (of programming languages)

I've been bitten by the Lisp bug last year, and it's not getting any better.

It's a pastime of mine to feel immensely frustrated with the status quo of software and computer programming in general, how clunky, unstable and unwieldy modern applications are, and how the programming community just collectively shrugs and mumbles something about layers of abstractions.

Applications are terrible because operating systems are terrible, and operating systems are terrible not because everybody is an idiot, but simply, like Alan Kay loves to remind us, we are still in the Stone Age of software engineering and are trying to build spaceships out of sticks and stones.

Software engineering in 2023, colorized.
Software engineering in 2023, colorized.

The reason Lisp has achieved its legendary status is that it is freeform and can represent any concept, technique and programming pattern. Lisp is no less expressive than a blank piece of paper, where any idea can be represented into it, if you know how to express it in words. Lisp is merely an unambiguous, machine-readable representation of symbolic processes. Mind you, its power doesn't lie in the parentheses themselves, but rather because of its homoiconicity. Language is homoiconic, and so is human thought: they are able to rewrite and transform themselves, and as such, they are potentially able to teach themselves to convey any concept. It's not a coincidence written text is the basis of human civilization, and can represent any past, present and future idea, concept, abstraction.

Our programming environments are tools we use to understand and control more efficiently our world, but also, they are literally tools just like a screwdriver is a tool. At the time of writing, we have been inventing better and smarter screwdrivers, but a screwdriver can only do so many things, it cannot describe reality itself. I don't know, Mr. Kay, when we'll leave the Stone Age of computing, but I am certain it will be the day we are able to program a computer with a language that transcends the physical and logical constraints of the hardware it runs on. Adding static typing to your screwdriver is a conceptual dead end.

On Lisp

I have known of Lisp and played with it a few times in my career, but the Hacker News hivemind, especially the hackers of old that post there and love to reminisce about what we have lost, keep infecting unsuspecting readers and junior engineers. Lately I have had a lot of free time to dive into its history, its teachings, its impact and why the hell is Lisp a relic of a bygone era, but also a glimpse towards the future of computing, the first milestone to computers truly being extensions of our minds.

There's this dream project that has been buzzing around my head for literally months. It's a piece of digital performance art: Imagine an operating system, that after boot simply prints:

> _

It's a Lisp REPL, with a twist. It supports all the special forms McCarthy designed 63 years ago, with an additional one: the ability to tell the CPU to jmp to the location of a binary string. If you can construct bytes in memory and jump to them, you can write and execute machine code. If you have a homoiconic language, you can represent any program. Such a REPL will be able to do literally any operation on your computer, including interfacing with all attached hardware. Writing machine code as binary strings is not fun, but you got a Lisp at your hands. Write an assembler. If you know the memory location of the REPL's eval function, you can replace it with a more efficient one. You can do literally anything.

The goal of this project is not practicality. The goal is to figure out what is the most minimal operating system/REPL/language combo that can represent any single operation of the underlying hardware. The secret sauce is, of course, Lisp. The secret sauce is homoiconicity.

But, to be honest with you, I haven't been able to dive very deep into the world of S-expressions with actual Lisp implementations because, frankly, they're all a bit shit. I might rant about it on a later post. So I've been designing one in my head, the Holy Grail of Lisp languages, and that involves doing a lot of reading about what's been tried in the past 63 years, and they've been doing things decades kid like us these days still just dream about. (This research has stopped two decades ago, when everybody got complacent and paid tons of money to write terrible software in screwdriver languages).

Yet something is still missing from my Lisp-flavoured Holy Grail, and it's taken me a long time to track down what's not ideal about Lisp's level of abstraction.

Bait and switch

In fact, this post is not about Lisp.

I love Elixir and Erlang. The real world is best modelled as actors that communicate, a concept bastardised by the OOP priests of the 90s, much to the chagrin of Alan Kay, yet beautifully implemented on the Erlang's BEAM virtual machine. Humans think sequentially, but modern CPUs, networked servers, life and reality themselves are (massively) parallel. Organisation arises by the communication between simple actors. This concept has been explored by that same person I have been referencing throughout the post in his language Smalltalk.

Smalltalk is cool, I guess. See, I'm a practical person. I dislike purely academic research, and the second reason I have been snobbing it until recently is because nobody uses it (the first reason is that I tend to discount things I'm ignorant about). Smalltalk is a tech demo of a futuristic system centuries ahead of our little screwdrivers, yet no one has written actual software with it. Not even their own orange-tinted forum. Modern engineers are conditioned to open their editor, or a REPL, and start mashing the keyboard, not running a self-contained operating system, clicking words in a dozen small windows set in sans serif font. This is not Smalltalk's fault, just a sign of our computing times.

The beauty of Smalltalk is that everything is a communicating object. And it's homoiconic. You don't need macros if you got objects all the way down. Objects can represent anything, including operations executed remotely and serialised through the wire. The golden age of computing will start the day we are able to model our virtual, digital world as an infinity of communicating systems, each system a simple-to-understand, serial list of instructions for a CPU to execute. Systems might be local (processes, CPU cores themselves) or transparently remote. The physical location of a system should be effectively inconsequential.

Communication should not be a small layer you add on top of a program to interact with the world, but it should be a central paradigm.

Baby, you got a stew going

I've been working on this idea, I'm not sure if it's good or not just yet. Today I've forced myself to take a few hours break from the hyperfocused flow mode of exploring what seems to me to be a novel yet familiar step towards this computing utopia, and I wanted to serialise and distill into words the million of concepts that have been buzzing around in my head over the past year.

Basically I've put Lisp, Smalltalk, Self (a Smalltalk dialect with an interesting idea), Io, Rebol (it is criminal how underrated and how mismanaged this language has been) together into a blender and I think I've got something worth exploring. The goal is a practical and pragmatic language based on communicating systems. The syntax is still being defined, but right now it looks like this:

name := IO readline
"Hello, " append: name, append: "!" println

I'm using Guile Scheme to write the REPL (I got frustrated with both Chicken Scheme and Common Lisp) and, unless I abandon the project halfway, which is very likely, I'll announce it properly at a later date.

I have a great name already, so most of the work is basically done.

View all posts