The Jsonnet Language Reference has this to say about Jsonnet functions:
Functions in Jsonnet are referentially transparent, meaning that any function call can be replaced with its definition, without changing the meaning of the program.
Then why does the following Jsonnet program:
{
c: local a = function() self.b; {x: a(), b: 'inner'},
b: 'outer'
}
manifest as follows:
{
"b": "outer",
"c": {
"b": "inner",
"x": "outer"
}
}
whereas the following program, which is the same as the first but for replacing the function a
by its definition:
{
c: {x: self.b, b: 'inner'},
b: 'outer'
}
manifest thus:
{
"b": "outer",
"c": {
"b": "inner",
"x": "inner"
}
}
which is different from the manifestation of the first program in the value associated with the x
key?
3
self
is special 🙂
I think that the issue is that local a = function() self.b;
is being immediately/serially evaluated (i.e. no lazy evaluation, as every local
), hence it gets that self
“collapsed” into its value at that time.
If you want that function to be lazy-evaluated, you’d need to pass such reference, for example (note I dupped the function verbatim for c
and cRoot
for the sake of just showing the same construct):
foo.jsonnet
{
c: local a = function(ref) ref.b; { x: a(self), b: 'inner' },
cRoot: local a = function(ref) ref.b; { x: a($), b: 'inner' },
b: 'outer',
}
output
{
"b": "outer",
"c": {
"b": "inner",
"x": "inner"
},
"cRoot": {
"b": "inner",
"x": "outer"
}
}
2