4 ms·
It's funny that behind the scenes in all languages, everything is lists (in the AST). It's strange that we tend to initially code in easily readable built-in c
by valty 3y ago
It's funny that behind the scenes in all languages, everything is lists (in the AST).
It's strange that we tend to initially code in easily readable built-in control structures (if, switch, for, while), but then there always comes a point when you need to refactor...and convert them into lists of data structures and process those.
For example, if you are matching routes in a web server, you can write a bunch of if-statements. Very simple. Easily understandable. And you can use whatever criteria you want, in whatever order you want.
if (request.pathname == '/foo') { return foo }
if (request.pathname == '/bar') { return bar }
But say now you want to print a list of all the routes and how they are matched.
Most people create a concept of a `Route` object that contains a predicate, and then you loop over those in a list. It feels super clean. But now if you want an exotic way of matching a particular route, or you want route priority or anything like that, and your route matcher and Route objects start becoming really complex...but if you did it with a simple code block with if statements, it would have been really easy.
const routes = [
{pathname: '/foo', action: () => {}},
{pathname: '/bar', action: () => {}},
]
for (const route in routes) {
if (route.pathname === request.pathname) { return route.action }
}
If we could have referenced our if-statement code blocks as a list (using Reflection or something), then we could have avoided any abstraction and stayed totally flexible.
I could easily throw a few more requirements at you, and you would quickly have some frankenstein Route object and matching logic.
It's this weird process of "dont-repeat-yourself" where everything looks the same and you abstract it, and then you realize its not all the same, and instead of back-tracking the data structure, you just tack on new stuff and more complicated logic.
Complexity in software stems from these pre-mature abstractions.
- tangentstorm 3y agoYes but in whatever language you're imagining here, a "list" probably isn't the kind of list that lisp uses (linked lists of cons cells).
- skybrian 3y agoIt's not true that everything is a list in most languages. Typically an AST is built with both lists and structs. Special forms are always going to exist and the code needs to deal with them, so this isn't a loss; it's being more explicit. Well-named fields are better documentation and faster than accessing the nth item than a linked list. (You can emulate named fields using just lists, but it's just a convention.) Also, in most languages, the lists aren't linked lists. They're typically array-backed. JSON has both lists and objects (which serve as structs) and it's quite popular and usable for representing AST's.