Abstraction, Not Syntax
Posted3 months agoActive3 months ago
ruudvanasseldonk.comTechstoryHigh profile
heatedmixed
Debate
80/100
Configuration LanguagesAbstraction vs SyntaxTuring Completeness
Key topics
Configuration Languages
Abstraction vs Syntax
Turing Completeness
The article 'Abstraction, not syntax' discusses the trade-offs between simple configuration formats and more abstract, programmable ones, sparking a debate on the merits of Turing completeness in configuration languages.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
12h
Peak period
22
12-15h
Avg / period
6.5
Comment distribution65 data points
Loading chart...
Based on 65 loaded comments
Key moments
- 01Story posted
Oct 13, 2025 at 4:45 AM EDT
3 months ago
Step 01 - 02First comment
Oct 13, 2025 at 4:39 PM EDT
12h after posting
Step 02 - 03Peak activity
22 comments in 12-15h
Hottest window of the conversation
Step 03 - 04Latest activity
Oct 14, 2025 at 8:19 PM EDT
3 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45566198Type: storyLast synced: 11/20/2025, 8:52:00 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
It is specifically saying the same problem exists in JSON/YAML/TOML, etc, which is that all these configuration languages don't have any real means of abstraction, and ultimately aren't expressive enough do to the job we require of them.
as soon as you are templating config files with other configs, I agree, I have sorely felt this limitation with helm charts
There is no single cure-all, of course, but surely we should be relying on computers to do much of the heavy lifting when it comes to validation and verification of these files, not just as linters after the fact but in realtime while we're editing, and with some sort of knowledge (even if derived programmatically) of what is right and what is wrong so we no longer have to worry about simple footguns.
But when working with real programming languages it is completely different, you can take semantic information from the current code, and you can have things like types to give you safety.
Trying that on Google gets me https://en.wikipedia.org/wiki/Sayre%27s_law. Is about right. :D
Don't want to sound too harsh, but to me HCL is even worse than plain YAML.
By expressiveness, HCL is somewhat similar to Ansible-flavoured YAML - in both you need to use magic keywords to create any kind of abstraction (e.g. a loop).
HCL is worse than regular YAML because there's only one "true" parser for it, that is official Hashicorp's HCL parser. So if you are locked into Golang ecosystem, then sure it can work for you, otherwise you are out of luck.
There are a couple of tools that convert HCL into JSON, I tried both, they somewhat work, but in the end of the day it's a big hack. At that point I just gave up on using HCL and started using something else that generates JSON.
Hope you find some configuration layer that fits your users more than HCL or YAML.
But anytime someone suggests TOML I have to double check to be sure they are serious because the TOML syntax for anything more complicated than single-layer maps is mind-bogglingly confusing to me. This is not a serious alternative to YAML.
And for those that haven't taken a look at it, the "customize" menu and everything it supports is silly impressive. And it just writes out the results out, like a boss.*
* Obviously, it has a lot of "don't edit below this line" complexity to it. But that doesn't change that it is right there.
Keep adding more edge cases and you have something resembles JSON
Lots of config.json is being replaced by the nicer config.ts.
Also I've been in projects where I had to debug the config multiple levels deep, tracking side-effects someone made in some constructor trying to DRY out the code. We already have these issues in the application itself. Lets not also do that in configurations.
You need something between JSON/YAML and Python/JavaScript.
A config language makes the possibility space small.
It also makes it deterministic for CI and repeatable builds.
It also makes it parallelizable and cacheable.
Don't use your language for config. People will abuse it. Use a config language like Starlark or RCL.
Instead, there’s a another software in the configuration of sample projects, instead of just using good code organization and sensible conventions.
Actually that's not the biggest benefit (which is tests for schemas) but it's nice to have the “.ts” file actually log the actual config as JSON and then the app consumes it as JSON, rather than importing the .ts file and all its dependencies and having weird things like “this configuration property expects a lambda.”
Counterpoint: 95% of config-readers are or could be checked in with all the config they ever read.
I have yet to come across a programming language where it is easier to read + parse + type/structure validate a json/whatever file than it is to import a thing. Imports are also /much/ less fragile to e.g. the current working directory. And you get autocomplete! As for checks, you can use unit tests. And types, if you've got them.
I try to frame these guys as "data values" rather than configuration though. People tend to have less funny ideas about making their data 'clean'.
The only time where JSON.parse is actually easier is when you can't use a normal import. This boils down to when users write the data and have practical barriers to checking in to your source code. IME such cases are rare, and most are bad UX.
> Side effects in constructors
Putting such things in configuration files will not save you from people DRYing out the config files indirectly with effectful config processing logic. I recently spent the better part of a month ripping out one such chimera because changing the data model was intractable.
It is good to have a simple, declarative entry point to the build system which records declarative elements of the build. The non-declarative elements of the system are configuration-as-code.
Have used everything from Json to Cue and in-between. Tired of the context switch. Need to use SQL anyway. Fewer dependencies overall required.
I never relied on it for developer notes. Just arguing semantics in those cases.
- Turing completeness means that you have to deal with the halting problem, meaning you can't statically ensure that a program ever completes. This is really shit when dealing with config, one buggy while loop or infinite recursive function and stuff just grinds to a halt with no good way of debugging it. Having this problem at the config level might mean that your program never even gets to properly start up, so you never get to setup the logging / otel or whatever you usually use to catch those problems.
- Normal programming languages have side effects and are therefor insecure! They can usually read and write files anywhere, open sockets, send traffic over the internet, etc. These are all properties you don't want of a config language! Especially if you can import code from other modules, a single import statement in a "config file" is now a huge security risk! This is why "npm" keeps having security nightmares again and again and again.
So what you want from a config language is not the same thing as from a programming language, you want as much power as you can get without "Turing completeness" and without any "side effects". That's the reason we have stuff like HCL and whatever the article used as an example.
This isn't syntax vs abstraction. This is how much programming language power do you want to enable in your configuration language. This is a big difference and I think we miss the interesting part of that discussion because we dip into this 'abstraction angle.
If you want configuration-as-code use Python. Please. Or Tcl if you must. Do not invent N+1 DSL for your engineers to waste time learning.
Example: We are programming a backend for a blog. If we were to not use templates, but instead try to get that functionality via the webservice configuration we would have to "invent" some format that gives us the flexibility of templates within let's say a YAML file.
Needless to say that would be a horrible idea. Maybe I am being naive here, but I have yet to be convinced of the fact that it is really configuration formats that are the problem and not what people try to abuse them for. I have yet to work on a project where TOML wasn't enough for actual configuration.
Usually when I need something more complex than what can be done with TOML it is a sign that this needs to be handled differently. Via templates or with a database or making a special DSL-like script file. E.g. if you're using python nothing (except security considerations) stops you from allowing users to use a python file for configuration. If your configuration needs are really that complex, why not use a real programming language for it?
- Decision tree, where you only need comparison operators. The leaves are a specified list of actions.
- actions list with macros (variables). You can be fancy and add some conventions for arrays.
Anything more that that should just be a programming language. And if the relationship is adversarial (saas), you should really think hard about needing something that complex.
The specific problems in the example could be solved by changing how the data is represented. Consider the following alternative representation, written in edn:
This prevents issues where the region is mistyped for a single bucket, makes the interval more readable by using a custom tag, and as a bonus prevents duplicate bucket names via the use of a map.Obviously this doesn't prevent all errors, but it does prevent the specific errors that the RCL example solves, all without introducing a Turing-complete language.
Finding the "right" representation for a given set of data is an interesting problem, but most (all) of the time the representation is specified by someone/something else.
In the past I've written a [preprocessor][1] that adds some power to the representation while avoiding general purpose computation. For example,
Macros, basically. Arithmetic would help there, but that might be too much.[1]: https://github.com/dgoffredo/llama
YAML has a merge key <<:, which might be helpful.
The merge key is a clever little trick, but it depends of the special hash key, so lists can’t be merged.
Syntax does matter, which is why YAML matters — even if imperfect.
Doesn't help every yaml parser has their own opinion on what a merge or an anchor should do, exactly.
I'll try dig out a link to the talk one of their Flight Software Engineers did on the concept.
[1] https://www.stokespace.com/
[1]: https://news.ycombinator.com/item?id=45291858
Nor is it clear to me how the "for loop" version would handle the case where exceptionally one bucket is different. Which is a more interesting discussion imho, that's the whole point of having it as a configuration field, after all.
I'd be interested to hear from someone involved with early Borg/K8s development what the original intention was.
They are Turing complete. Leaving off any of the three features (difficult for the y-combinator) yields a non-Turing complete language, for example Sieve Script for filtering email lacks (c).
What the definition doesn’t cover is parameterization. Some people call this abstraction. Technically, lisp macros also fall under parameterization.
With parameterization it really seems like any and all functions, mappings, and operators that fail to be injective and composable are counter-productive in practice. The math term is "generative effects".
There seems to be this continuous contention between one side that wants its configuration files to basically be CSV and another side that, effectively, wants a full-blown programming language as their "configuration language".
Both sides have a point. Just happen to land in the "essentially CSV" camp myself. Even a lisp macro can generate CSV.
(Yes the phrase "universal language" is very difficult to search for if the specific academic term above is under consideration.)
As this article gets at, config files are one of those things, and they benefit hugely from the rampant abstraction violation of skipping an intermediary text format between the program doing the configuration and the program doing the work.
*or have internal versions of their APIs available in matching languages.
the article talks about the trade off between plain data structure versus abstract ones and that’s the main issue
the answer is both a faux programming language, and really bad ux / really hard to read / scan
maybe what they need is a program that generates better readable text; and somehow you can flip between the determinism of code and ux of readable text?!
(is that possible)