将对象与 +(加号运算符)与空白组合
Combining objects with + (plus operator) vs whitespace
Jsonnet 的文档提到 +
运算符可用于 inheritance, or, as it's worded in the tutorial, to combine objects:
{
a: 1,
b: 2,
}
+
{
a: 3
}
但是,我注意到 - 至少在像上面这样的简单情况下 - 简单地省略 +
运算符并写入由空格分隔的两个连续对象编译为相同的结果。也就是说,上面的程序和这个程序的输出没有区别:
{
a: 1,
b: 2,
}
{
a: 3
}
我很困惑,因为我没有注意到文档中有任何提及这种隐式对象组合。我还注意到这种行为似乎是对象独有的,其他类型不会发生。 (特别是,尽管 Jsonnet 的某些功能从 Python 中汲取了灵感,但您 不能 像在 Python 中那样隐式地将字符串与空格连接起来。)
因此,一些问题:
- 这是有意为之的行为还是错误?
- 它有任何记录吗?
- 使用显式
+
运算符组合对象与使用空格隐式组合对象之间是否存在任何行为差异?
一位同事建议我在教程的 Object Orientation 部分中提及这一点:
Let's make it more concrete by mixing deriving some cocktails that are quite similar from a template that draws out their similarities. The +
operator is actually implicit in these examples. In the common case where you write foo + { ... }
, i.e. the +
is immediately followed by a {
, then the +
can be elided. Try explicitly adding the +
in the 4 cases, below.
local templates = import 'templates.libsonnet';
{
// The template requires us to override
// the 'spirit'.
'Whiskey Sour': templates.Sour {
spirit: 'Whiskey',
},
// Specialize it further.
'Deluxe Sour': self['Whiskey Sour'] {
// Don't replace the whole sweetner,
// just change 'kind' within it.
sweetener+: { kind: 'Gomme Syrup' },
},
Daiquiri: templates.Sour {
spirit: 'Banks 7 Rum',
citrus+: { kind: 'Lime' },
// Any field can be overridden.
garnish: 'Lime wedge',
},
"Nor'Easter": templates.Sour {
spirit: 'Whiskey',
citrus: { kind: 'Lime', qty: 0.5 },
sweetener+: { kind: 'Maple Syrup' },
// +: Can also add to a list.
ingredients+: [
{ kind: 'Ginger Beer', qty: 1 },
],
},
}
因此,隐式对象组合:
- 合法
- 已记录,但似乎仅在教程和 formal spec 中,目前不在语言参考中
- 的行为与
+
相同,只是它仅在第二个操作数以 {
开头时可用,而不是在它是变量时可用。
它在 Google GCL 和 Borgcfg 模板语言中也是这样工作的。第一个子句的值是一个 map/template 对象。附加子句 { a: 3 } 只是对前面 map/template 对象中现有值的覆盖。我想这也是设计师为 jsonnet 设计的,因为它也来自 Google.
仅供参考,Borg/GCL 中的 + 运算符做了更糟糕的事情,它在合并映射之前评估运算符两侧的所有内容,这使得它在大多数情况下几乎无用。在 GCL/Borgcfg 中,您通常想要的是获取一个内部包含函数的模板,编辑一些模板,然后通过对影响函数的变量进行新赋值来实例化它,这在 + 运算符之后是不可能的,因为 welds/binds 在合并映射之前立即将所有变量添加到模板中 -- 太早了 -- 使它的用处很小 -- 这是 GCL 早期语言设计者犯的错误。
Jsonnet 的文档提到 +
运算符可用于 inheritance, or, as it's worded in the tutorial, to combine objects:
{
a: 1,
b: 2,
}
+
{
a: 3
}
但是,我注意到 - 至少在像上面这样的简单情况下 - 简单地省略 +
运算符并写入由空格分隔的两个连续对象编译为相同的结果。也就是说,上面的程序和这个程序的输出没有区别:
{
a: 1,
b: 2,
}
{
a: 3
}
我很困惑,因为我没有注意到文档中有任何提及这种隐式对象组合。我还注意到这种行为似乎是对象独有的,其他类型不会发生。 (特别是,尽管 Jsonnet 的某些功能从 Python 中汲取了灵感,但您 不能 像在 Python 中那样隐式地将字符串与空格连接起来。)
因此,一些问题:
- 这是有意为之的行为还是错误?
- 它有任何记录吗?
- 使用显式
+
运算符组合对象与使用空格隐式组合对象之间是否存在任何行为差异?
一位同事建议我在教程的 Object Orientation 部分中提及这一点:
Let's make it more concrete by mixing deriving some cocktails that are quite similar from a template that draws out their similarities. The
+
operator is actually implicit in these examples. In the common case where you writefoo + { ... }
, i.e. the+
is immediately followed by a{
, then the+
can be elided. Try explicitly adding the+
in the 4 cases, below.local templates = import 'templates.libsonnet'; { // The template requires us to override // the 'spirit'. 'Whiskey Sour': templates.Sour { spirit: 'Whiskey', }, // Specialize it further. 'Deluxe Sour': self['Whiskey Sour'] { // Don't replace the whole sweetner, // just change 'kind' within it. sweetener+: { kind: 'Gomme Syrup' }, }, Daiquiri: templates.Sour { spirit: 'Banks 7 Rum', citrus+: { kind: 'Lime' }, // Any field can be overridden. garnish: 'Lime wedge', }, "Nor'Easter": templates.Sour { spirit: 'Whiskey', citrus: { kind: 'Lime', qty: 0.5 }, sweetener+: { kind: 'Maple Syrup' }, // +: Can also add to a list. ingredients+: [ { kind: 'Ginger Beer', qty: 1 }, ], }, }
因此,隐式对象组合:
- 合法
- 已记录,但似乎仅在教程和 formal spec 中,目前不在语言参考中
- 的行为与
+
相同,只是它仅在第二个操作数以{
开头时可用,而不是在它是变量时可用。
它在 Google GCL 和 Borgcfg 模板语言中也是这样工作的。第一个子句的值是一个 map/template 对象。附加子句 { a: 3 } 只是对前面 map/template 对象中现有值的覆盖。我想这也是设计师为 jsonnet 设计的,因为它也来自 Google.
仅供参考,Borg/GCL 中的 + 运算符做了更糟糕的事情,它在合并映射之前评估运算符两侧的所有内容,这使得它在大多数情况下几乎无用。在 GCL/Borgcfg 中,您通常想要的是获取一个内部包含函数的模板,编辑一些模板,然后通过对影响函数的变量进行新赋值来实例化它,这在 + 运算符之后是不可能的,因为 welds/binds 在合并映射之前立即将所有变量添加到模板中 -- 太早了 -- 使它的用处很小 -- 这是 GCL 早期语言设计者犯的错误。