Things I Don't Like in Configuration Languages
Spoiler: I created my own configuration language maml.dev
Here will be a list of all markup languages/configuration languages I found on the internet, and things I don't like about them.
YAML
- - 1
- 2
- - 3
- 4
YAML 1.2 is better than YAML 1.0. But still, the YAML specification is monstrous, and I don't get how people trying to implement it are not going insane. YAML contains too many features.
XML
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://ex.com/catalog"
xmlns:cat="http://ex.com/catalog"
xmlns:old="http://ex.com/oldcatalog">
<item id="0042">
<name>R&D Handbook</name>
<notes priority="1 2 3">n/a</notes>
</item>
</catalog>
The era of XML is in the past. I remember the hype around XML, how it was thought to be a universal format, and people created a lot of stuff around it. But now it's dead.
JSON
{"name": "John", "age": 30, "car": null}
JSON is nice and JSON won. It's a universal, data-interchange format for the Web and applications. This is why I based my MAML on top of JSON. I fixed things that were a little bit annoying for me inside JSON.
TOML
[[servers.web]]
name = "frontend"
ip = "192.168.1.10"
[[servers]]
region = "eu-central"
[[servers.web]]
name = "backend"
ip = "192.168.1.11"
I don't get why the [table] is more readable, and I don't understand [[array of tables]] out of order.
And the lack of null.
JSON5
{
lineBreaks: 'Look, Mom! \
No \\n\'s!',
hexadecimal: 0xdecaf,
a: +.8675309, b: +8675309.,
}
Too many unnecessary features. Object key-value pairs are still unordered. No distinction between integers and floats.
HJSON
{
Hjson: a string
RegEx: \s+
md:
'''
First line.
Second line.
This line is indented by two spaces.
'''
}
Unquoted strings and three different types of comments. Multi-line strings with significant indentation.
JSONH
{
// use #, // or /**/ comments
keys: without quotes,
isn\'t: {
that: cool? # yes
}
}
JSONH is same as HJSON but different.
RJSON
{
shopping-list: [ milk butter /* don't forget the beer */ beer ]
a\ space : t\:em item\ with\ spaces
}
Strings without quotes, but only if they don't contain spaces or commas. No specification.
JSONC
{
/*
This is a multi-line comment
that spans multiple lines
*/
"name": "Jane Doe",
"age": 25,
}
There are so many implementations and differences in implementations of JSON with comments. For example, this one has trailing commas. Still allows duplicate keys, still no integers, unordered key-value objects.
HCL
service "aws_ami" "ubuntu" {
most_recent = true
instance_type = var.instance_type != "" ? var.instance_type : "t3.micro"
}
I don't like nesting with service "http" "web_proxy" or ability to specify service multiple times in different parts
of the file.
Pkl
class Bird {
name: String
hidden taxonomy: Taxonomy
}
pigeon: Bird = new {
name = "Common wood pigeon"
taxonomy {
species = "Columba palumbus"
}
}
This is not a markup language. This is a full-blown programming language. I honestly would just use TypeScript instead of this one.
RON
GameConfig( // optional struct name
window_size: (800, 600),
key_bindings: {
"up": Up,
"down": Down,
"left": Left,
"right": Right,
},
)
Very Rust-centric.
EDN
#:demo{:id #uuid "de305d54-75b4-431b-adb2-eb6b9e546014"
:ts #inst "2025-11-04T09:00:00Z"
:nums [1 2 3 4/2 5.5M]
:set #{:a :b :c}
:rx #"[A-Z]+"
:q #queue ["x" "y"]
:tag #user{:name "Zed"}}
I guess Clojure developers love it. I'm not one of them.
HOCON
include required("foo.conf")
a : [ 1, 2 ] [ 3, 4 ]
data-center-east = ${data-center-generic} { name = "east" }
{ foo include : 42 }
Too many features. Is it some sort of programming language? And it looks like it's very focused on just one project.
NestedText
default repository: home
report style: tree
compact format: {repo}: {size:{fmt}}. Last back up: {last_create:ddd, MMM DD}.
date format: D MMMM YYYY
size format: .2b
YAML variant with only strings. But I need booleans!
KDL
author "Alex Monad" email=alex@example.com active=#true
scripts {
message """
hello
world
"""
}
KDL is much closer to XML with properties on nodes. But I like JSON-like data structures. They are easier to understand. Also, I don't like significant indentation on multi-line strings.
SDLang
// Trailing semicolons are optional
prop true;
anotherprod on; author "Peter Parker"
this-is.1_valid$Tag-Name
renderer:options "invisible"
physics:options "nocollide"
title \
"Some title"
They do have true and false. Why adding on and off? By default, integers are 32 bits long. Suffix 10L is
needed for 64-bits.
CUE
import "math"
piPlusOne: math.Pi + 1
"quoted field names": {
"four^four": math.Pow(4, 4)
}
I would just use TypeScript instead of this programming language. Too many features; the specification is too big.
Dhall
let makeUser = \(user : Text) ->
let home = "/home/${user}"
let privateKey = "${home}/.ssh/id_ed25519"
let publicKey = "${privateKey}.pub"
in { home, privateKey, publicKey }
{- Add another user to this list -}
in [ makeUser "bill"
, makeUser "jane"
]
Again, it is a programming language. So I guess only one implementation of Dhall exists?
Jsonnet
local my_function(x, y=10) = x + y;
{
person1: {
name: "Alice",
welcome: "Hello " + self.name + "!",
},
person2: self.person1 { name: "Bob" },
len: [
std.length('hello'),
std.length([1, 2, 3]),
]
}
Well, this is some sort of programming language with dynamic types. But there are so many good programming languages, so I don't know why this one needs to be used.
Nickel
let conf = {
name = "NiCl",
version = "0.0.1$",
description = "My cool app!"
} in
let SemanticVersion = fun label value =>
let pattern = "^\\d{1,2}\\.\\d{1,2}(\\.\\d{1,2})?$" in
if std.string.is_match pattern value then
value
else
let msg = "invalid version number" in
std.contract.blame_with_message msg label
in
let AppSchema = {
name | String,
version | SemanticVersion,
description | String,
} in
conf | AppSchema
Nice programming language. Not a markup language.
Starlark
def fizz_buzz(n):
"""Print Fizz Buzz numbers from 1 to n."""
for i in range(1, n + 1):
s = ""
if i % 3 == 0:
s += "Fizz"
if i % 5 == 0:
s += "Buzz"
print(s if s else i)
fizz_buzz(20)
Starlark is a programming language. Good lack porting/reimplementing Starlark in another programming language.
UCG
let tuple = {
inner = {
field = "value",
},
list = [1, 2] + [3],
"quoted field" = "quoted value",
};
This is just an implementation of a language. Not portable to other languages.
UCL
.include "${CURDIR}/path.conf"
.macro_name(param={key=value}) "something";
section "blah" "foo" {
key = value;
}
Okay. An implementation of a configuration language. No specification. No other implementations.
Confetti
probe-device eth0 eth1
user * {
login anonymous
password "${ENV:ANONPASS}"
machine 167.89.14.1
proxy {
try-ports 582 583 584
}
}
Nice logo! But other than that, I found it difficult to understand what's going on in this example. What about escaping in strings?
Ziggy
{
.name = "ziggy",
.version = @v("1.0.0"),
.license = @spdx("MIT"),
.dependencies = {
"react": "next",
"leftpad": "^1.0.0",
},
.repository = Git {
// "type" is now the struct name
.url = "https://github.com",
},
.description =
\\# Ziggy
\\
\\A Data Serialization Language.
,
}
I actually liked the idea of differentiating structs and maps. But this is just an implementation of a tool. No specification. And I don't like Zig-style multiline strings.
HUML
website::
ports:: 80, 443
enabled: true
factor: 3.14
props:: mime_type: "text/html", encoding: "gzip"
tags::
- "markup"
- "webpage"
- "schema"
Nice idea to make YAML less worse. But it's still a YAML, with the same problems and significant indentation.
MAML
{
project: "MAML"
tags: [
"minimal"
"readable"
]
# A simple nested object
spec: {
version: 1
author: "Anton Medvedev"
}
# Array of objects
examples: [
{
name: "JSON", born: 2001
}
{
name: "MAML", born: 2025
}
]
notes: """
This is a multiline raw strings.
Keeps formatting as-is.
"""
}
So, I decided to create a specification for my own language. And I wanted a distinctive name, not JSON something. I wanted a nice name and a strict specification. All languages have trade-offs. MAML as well.
Comments