1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
|
---
layout: default
title: Comparisons
---
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<h1 id="comparisons">Comparisons</h1>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<p>
This article attempts to describe the whole open source configuration space, and Jsonnet's
place within it. Needless to say this is challenging and this will be a living document.
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<h2 id="json">Comparison With JSON</h2>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<p>
JSON is used to describe data literally. Jsonnet extends JSON. Jsonnet has relaxed syntax
and comments to make it easier for humans to write. Jsonnet also adds constructs for
generating, translating and refining data. Because Jsonnet is an extension of JSON, valid
JSON is also valid Jsonnet that just emits that JSON unchanged.
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<h2 id="yaml">Comparison With YAML</h2>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<p>
YAML is also an extension of JSON that generates JSON. Like Jsonnet, YAML is intended to
improve the user experience when data is transferred over the human / machine boundary. Its
syntax is very tight; YAML files are much shorter than their JSON equivalents. However its
constructs for generating, translating, and refining data are very weak in comparison to
Jsonnet. Moreover, the tightness of its syntax makes it hard to extend YAML to add these
features. In particular, YAML and Jsonnet disagree about what 1+1 should mean. YAML
already defines it to mean the string "1+1", whereas in Jsonnet we want it to be 2. Jsonnet
therefore builds from JSON and not YAML.
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<h2 id="templates">Comparison With Other Templating Languages</h2>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<p>
Jsonnet is a form of templating language as it generates data from programs that interleave
verbatim data with computation constructs. However other templating languages operate on
plain text. That is to say that the data amongst which the computational constructs are
intermingled are simply plain text, and the output of the evaluation is also plain text.
This means such systems can be used to produce files with arbitrary syntax, e.g. custom
configuration file syntax, HTML, or even JSON.
</p>
<p>
However, since these templating languages are unaware of the syntax of the file they're
generating (they think it is simply plain text), they cannot help the programmer avoid
creating errors in the underlying representation.
</p>
<p>
By analogy, the C preprocessor has no understanding of C syntax. C preprocessor macros can
break that syntax if they are used wrongly. The net result of this is that problems with
the use of these macros must be debugged by examining the output of the evaluation (i.e. the
generated C code). Errors cannot be presented at the level at which the programmer is
actually working. For this reason, the vast majority of modern languages do not feature a
pre-processor.
</p>
<p>
The situation is the same when templating languages are used to generate HTML, often the
developer will check the generated HTML because successful evaluation of the template does
not imply the HTML is correct. The same is true when the target language is JSON. Jsonnet
avoids these problems, as although it is limited to JSON output, it is guaranteed that the
output will be valid JSON.
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<h2 id="functional">Comparison With Other Functional Languages</h2>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<p>
ML is a functional language like Jsonnet. However ML is not pure, and also has strict
evaluation. Haskell is a pure lazy functional language, but unlike Jsonnet it has static
type safety. Providing static type safety means programmers have to understand type
inference, unification errors, and also provide the occasional type annotation. Even then,
some correct programs are rejected.
</p>
<p>
The Nix expression language, which is a pure lazy functional language with dynamic typing,
is therefore closer to Jsonnet. Jsonnet differs from the Nix expression language mainly in
that it also has object-oriented semantics in the form of mixins. Also, Jsonnet is an
extension of JSON, whereas the Nix expression language is not (in particular it lacks
floating point numbers). Finally, the Nix expression language is an embedded part of the
Nix package manager (and other tools), whereas Jsonnet is a standalone evaluator that can
sit in front of anything that accepts JSON.
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<h2 id="scripting">Comparison With Other Scripting Languages</h2>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<p>
Most scripting languages are dynamically typed languages, often with object-oriented
features.
</p>
<p>
However, Jsonnet is also a templating language, which makes it very good for generating data
that is a mixture of verbatim and computed elements. Jsonnet programs can be easily
understood and modified by someone who only knows JSON. Any parts of the program which are
just JSON (i.e. do not make use of the extended Jsonnet constructs) can be modified with
predictable results. Jsonnet's pure functional semantics also make modifying the program
more predictable.
</p>
<p>
More importantly, Jsonnet has the property of hermeticity. This means that regardless of
when or where a Jsonnet program is evaluated, it will always generate the same JSON. This
means the program can be freely converted to data, and thus it can be thought of as
equivalent to data. This is not the case with general purpose languages, as they are
allowed to read files, contact the network, look up the time, or any number of other sources
of non-deterministic behavior. While it is possible to sandbox some scripting languages in
order to patch all of these holes, the result of this is a new language that is incompatible
with the original language. This makes Jsonnet a lot more suitable for configuration than
general purpose scripting languages.
</p>
<p>
One advantage that is often put forward for using general purpose scripting languages as
configuration languages is that they are already well-understood by a large number of
people. However this is also true of Jsonnet, because of its backwards compatibility with
JSON, its use of mixins (a decades old construct that is well-understood) and the mimicking
of Python syntax in cases where that makes sense (e.g. string formatting and comprehension
constructs).
</p>
<p>
Finally, Jsonnet is a much smaller language than most general purpose scripting languages,
yet despite this it has considerable expressive power.
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<h2 id="configuration">Comparison With Other Configuration Languages</h2>
</div>
<div style="clear: both"></div>
</div>
</div>
<div class="hgroup">
<div class="hgroup-inline">
<div class="panel">
<p>
<a href="https://code.google.com/p/coil/">Coil</a> is a configuration language that is
interpreted by a Python library. Like Jsonnet, it has a JSON-like data model and some
facilities for extending objects to avoid duplication, referring to other parts of the
structure, and importing from other files. However it is a long way from the expressiveness
of the object-oriented semantics of Jsonnet, and it also does not have the ability to do
arithmetic beyond substituting values into strings. Finally, coil binds variables according
to <a href="https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scope">dynamic
scoping rules</a>, which have long been discredited because they quickly make code very
difficult to understand. Jsonnet uses static scoping, like almost all mainstream languages.
</p>
<p>
<a href="https://github.com/wickman/pystachio">Pystachio</a> is a Python framework that
makes it easier to use Python itself as a configuration language. It extends Python's
existing data literals (which are JSON-like) to enforce immutability and add some templating
functionality. However it lacks the full computational abilities of Jsonnet. Although it
does allow some computation within string values via template expansion, the only variables
you can access are stored in separate "environments", and there is no direct access to the
data being configured. Even if we assume that all data is stored in environments and object
fields merely forward to the environment, the language does not have any true
object-orientation features. While scopes are inherited from outer objects, this just an
implicit way of doing what you can do in Jsonnet with <code>$</code> or <code>local</code>.
In Pystachio there is no way to derive a struct from another struct with a few changes, let
alone use late binding or the expressive power of mixins.
</p>
<p>
Finally, there are a number of other configuration languages that have grown to be used by a
range of applications. For example <a href="https://en.wikipedia.org/wiki/INI_file">INI
files</a> or <a href="https://httpd.apache.org/docs/2.2/configuring.html">Apache config
files</a>. Typically these offer few features beyond simple JSON and provide very little
functionality when compared to Jsonnet.
</p>
</div>
<div style="clear: both"></div>
</div>
</div>
|