Simple Programming Languages (
from to on 22 Mar 2024 01:29

In this post I want to make this kind of simplicity more precise and talk about some reasons it’s important. I propose five key ideas for simple programming languages: ready-at-hand features, fast iteration cycles, a single way of doing things, first-order reasoning principles, and simple static type systems. I discuss each of these at length below.

Aside: simplicity in languages is interesting. I’d say most popular languages, from Rust and Haskell to Python and JavaScript, are not simple. Popular PL research topics, such as linear types and effect systems, are also not simple (I suppose all the simple concepts have already been done over and over).

Making a simple language which is also practical requires a careful selection of features: powerful enough to cover all of the language’s possible use-cases, but not too powerful that they encourage over-engineered or unnecessarily-clever (hard-to-understand) solutions (e.g. metaprogramming). The simplest languages tend to be DSLs with very specific use-cases, and the least simple ones tend to have so much complexity, people write simpler DSLs in them. But then, many simple DSLs become complex in aggregate, to implement and to learn…so once again, it’s a balance of “which features have the broadest use-cases while remaining easy to reason about”?


threaded - newest on 22 Mar 2024 02:19 next collapse

I honestly don’t think there’s a single language out there that’s more approachable and straightforward than PHP - it has the perfect amount of built in functionality… it’s not overwhelming like Java but also doesn’t make you constantly reinvent the wheel like C++ - both Go and Python have similarly right-sized STLs.

The stand out though (which I admit is becoming less relevant) is in its natural habitat. It was a language designed to produce HTML and it is extremely trivial to casually start programming in it. Do you have a table and want to splat out 10 trs without writing them one by one - write it once and wrap it in <? for($i = 0; $i < 10; $i++) { ?> and a closing brace and, well, look ma I’m a hacker!

It is amazingly accessible and a large number of people had their first programming experience messing around with PHP. on 22 Mar 2024 08:18 collapse

You have to manually explain to the computer how to count to ten, in 2024, and you call that simple? Simple would be something like

<? 10.times { ?> on 22 Mar 2024 14:26 collapse

Even simpler is repeat 10 { }

} just stands for done. on 22 Mar 2024 02:44 next collapse

You mention that Haskell isn’t simple. That may be so. However, all of Haskell compiles down to Haskell Core which is incredibly simple. It’s similar with many languages. Purescript back end is being rewritten in Chez Scheme which is also incredibly simple.

My point is, if you stack enough simple layers on simple layers, things get very complex. on 22 Mar 2024 05:37 next collapse

That’s sort of obvious and seems to kind of miss the point of a programming language. A language is an abstraction over the capabilities of a (possibly virtual) machine. The machine itself can generally only do relatively simple things; but writing assembly code is usually more difficult than writing the same functionality in a higher level language, because individual machine instructions are such a small building block for designing higher-level behaviors. So it’s hardly surprising that simple layers stacked on each other result in complexity. The point of the article (and of language design in general) is about how to balance expressive power versus simplicity of language concepts. on 22 Mar 2024 08:23 next collapse

The machine itself can generally only do very simple things

I disagree. Assembly languages for modern architectures are a complexity hell. You need books with thousands of pages to explain how they work. In comparison the lambda calculus is much simpler. on 22 Mar 2024 23:29 collapse

I should have said “relatively simple”, not “very simple”. on 22 Mar 2024 12:39 collapse

The machine itself can generally only do very simple things

That really hasn’t been true for at least 2 decades. And nowadays assembly code is no more that another abstraction layer, as microcode in the processor becomes increasingly complex. It’s as out-of-date an idea as the idea that C code is ‘close to the metal’. on 22 Mar 2024 23:28 collapse

I should have said “relatively simple”, not “very simple”. Yes, modern assembly instructions can often be relatively complex (though not on all architectures). But the point is that every abstraction layer presents a simpler API compared to what’s below, but must be implemented in terms of complex combinations of the fundamentally simple units of functionality in the layer below it. This is true of assembly, yes, but that doesn’t make it less true of higher level languages. on 23 Mar 2024 13:58 collapse

Haskell is simple in some ways and complicated in others.

It doesn’t have optional or named parameters. There are no objects or methods. No constructors. It doesn’t distinguish syntactically between procedures and functions. There are no for loops or while loops. && and || aren’t treated specially. It doesn’t even have functions with more than one argument. Every function takes one argument and returns one result. on 22 Mar 2024 02:55 next collapse

It seems Rabbit has followed several of these principles… on 22 Mar 2024 06:08 next collapse

As someone with an odd relationship with programming, I suspect we have different definitions of simple. Though in fairness the problem with some languages (that I'd call simple) for me is with performance particularly when parallelism can't really be used, and I guess you could say that I expect too much.

The most programming I've done (admittedly, not a lot) was with Nim-lang because that seems to be the only thing I've seen that has style+performance that I want. I'm sure if you look inside the machines it's not simple for a lot of reasons, but it can be used simply if you pretend those things don't exist (particularly if you didn't know of them in the first place) and just make something script-like. And even stuff like memory management is tunable and optional. So yeah, a language that's simple-to-use and simple-to-maintain (create? understand? or just minimalist in general?) seem different to me. To take it to an extreme, something like Brainfuck seems like it'd the best example of a simple/small interpreter without being simple to read.

This is an example of the last code I tinkered with (input text example). I like the different ways of doing things (or just something like UFCS), maybe that's not simple for the language but it allows me to make my code simpler.

EDIT: Also watching an explainer for Gleam maybe it's less about flexibility but just some of the things looking odd (/not intuitive), which for sure could largely be on me. (maybe that would be a preference thing even for people who understand it)

Personal note, I stopped there because I wasn't quite sure on usage/implementation with different polygon types. Plus, part of me wanting the language to get out of the way would be for supplemental editors to exist (like a game engine) so I could do basic things (art, animations, GUIs) visually and save the code for actual logic. Still no bindings for Godot 4 (Godot 3 had production-ready bindings) which I suppose is due to Nim being niche. I could possibly use Raylib (or Godot 3) with 3D instead, but I have less motivation to do so (esp. learning/using Blender, though maybe I should given details). For context, this animated eye is an example of the aesthetic I'd go for (if it were viable, which it might not be). Also if that link looks broken, for whatever reason for me it loads as expected in a private window. on 23 Mar 2024 14:00 collapse

The Koka language has a stated goal to be as simple as possible. The language definition even has something like scheme’s “feature on top of feature” verbiage. However it’s a very different language than you’re thinking of.