2a. The language includes limited primitives for recursion or loops.
If that’s done right, somehow proving that your program will terminate becomes trivial.
For example, allowing looping over a previously defined array with (key,value1) pairs to generate many more complex definitions that include common value2, value3, etc fields trivially guarantees termination, but a generic “while” loop doesn’t.
That will make you language less powerful, but IMO shouldn’t be problem for a configuration language.
In this example, I’m not sure you would even need that, as the language has ways to share common config values.
See my examples with html un-escaping and mergesort, down the comment chain.
Limited recursion/iteration is ok if all you need is to fill existing values into a template and possibly reduce repetition.
But in a large system with many components I might want to take a single timestamp, parse it, and generate timestamps in five different formats for five different subcomponents.
Or I might want to generate a piece of yaml config for an Ansible playbook that needs it, and now my config language needs to know how to escape yaml strings.
Or a config for a static site generator needs to be able to calculate a hash of a local css file because I’d like to use links like `style.css?hash` (a popular cache-defeating mechanism).
Or a certain path has to be split on “.” and reversed (Java-style com.example.blah things).
Or a Unix path needs to be converted to a Windows path, except [some special-cased paths that live in a map in an adjacent config].
There are endless reasons to want arbitrary logic in my config files, beyond reducing repetition. A lot of things I’ve listed are provided as primitives in various config/templating languages, but you always end up stumbling upon something that’s not provided.
Of course, one could say “You should use a real programming language for this kind of stuff”, and I’m happy that the JavaScript ecosystem is converging on allowing .js/.ts files for configs, because that’s exactly what I want too. But I’d like to have the same features available in projects that aren’t allowed to touch JS.
2a. The language includes limited primitives for recursion or loops.
If that’s done right, somehow proving that your program will terminate becomes trivial.
For example, allowing looping over a previously defined array with (key,value1) pairs to generate many more complex definitions that include common value2, value3, etc fields trivially guarantees termination, but a generic “while” loop doesn’t.
That will make you language less powerful, but IMO shouldn’t be problem for a configuration language.
In this example, I’m not sure you would even need that, as the language has ways to share common config values.