|
|
|
|
|
by gf000
19 days ago
|
|
My issue is that a language is just as much about what it disallows, as much as about what it allows. It's absolutely trivial to allow everything, you just have to make a Turing-complete extension either by design or accidentally. It's much much harder to carefully choose more limiting primitives that only allow you to build stuff that keep certain important properties about them. You can't subtract stuff after the fact. E.g. something like rust's borrow checker could not be realistically implemented as "a lisp" macro (what does lisp even mean in this case). For that to work you would literally build a rust compiler over s-expressions and you might as well leave off the s-expressions at that point. And every part that was not compiled by that macro or whatever would be unsafe and could not interact with the "rust-lisp" compiled parts, as you can no longer assert anything about them (there is nothing mandating the usual single writer, xor multiple read-only references laws) |
|
Rust is more restrictive than Lisp. These restrictions are sane and productive for most general software development in 2026. They form an excellent base to start your work in this day and age. Starting with raw Lisp feels like starting with the general notion of mobility instead of just getting in a car. The car is not inferior at all. It's a set of restrictions on the most general notion of mobility that in fact buy you a lot of comfort like knowing it doesn't need to eat hay or take a poo in the street. The freedom they take away, they give back in strong, useful guarantees about stuff you actually care about ("getting places").
I can see how Rust, Haskell or whatever provide a set of comfortable, general-enough restrictions to make life for the common developer easier and more productive.
This being HN I do want to allow myself some contrarianism and point out that finding the most minimal, yet most general computational substrate is not at all trivial. It's in some ways equivalent to finding the most minimal set of invariants ("laws of physics") that can describe the most wide range of phenomena ("nature"). Which is to say I find it pretty damn impressive. So I only "disagree" with this:
> It's absolutely trivial to allow everything
I don't disagree because it is wrong, it's clearly not. Turing shows all languages collapse into one when it comes to computational power and I don't doubt that. But I do know there is a distance between the computational substrate, the primitives of the language, and the structures it expresses. Let me give an example.
A spreadsheet can represent a computer game. A game engine can represent a spreadsheet. But if you build Excel inside Unity you haven't made Unity spreadsheet-like at the substrate level; you have encoded spreadsheet semantics in Unity's primitives. Functionally they may be equivalent, and that equivalence is beautiful and Turing can tell you all about it, but the relationship between the native primitives and the concepts being expressed is different.
Turing makes building endless towers that are functionally equivalent possible, but what I mean is that there is an architectural difference between a system directly built out of the least semantically committed substrate available to it ("native") or "embedded" in simulations of substrates built on top of those primitives.
I think Lisp is close to the "least semantically committed substrate" you'll ever come across in practice. It's certainly not the only one, but it's a particularly clean and relatively practical one. One can say, for example, raw lambda calculus is equally uncommitted but it's kind of .. hairy. Lisp's primitives are basically the machinery of symbolic manipulation itself. It's bloody amazing.
Sorry for the verbiage. I went way overboard and meandered into foggy, mystical meadows full of mysterious entities so feel free to ignore.
Have a nice weekend!