Reputation: 18534
I would like to increment a counter in a method, like this:
row(title, height):: {
_panels:: [],
_panelSlot:: 0,
addPanel(panel):: self {
self._panelSlot = self._panelSlot + 1,
_panels+: [{
slot: panelSlot,
panel: panel,
}],
},
The line self._panelSlot = self._panelSlot +1
is what I have expected to work, however that does cause the following error:
STATIC ERROR: lib/grafana/builder.libsonnet:157:7-11: unexpected: self while parsing field definition
My second try:
I'm unsure whether this would overwrite the _panelSlot
variable, but I couldn't confirm because I failed to access that variable on my object array:
row(title, height):: {
_panels:: [],
// height is the row's height in grid numbers and it is used' to calculate the
// panel's height and y pos accordingly.
_height:: height,
// panelSlot is the row panels' current position from left-to-right. If there are
// two or more stacked panels they share the same slot. This is used to calculate
// the width for each panel.
_panelSlot:: 0,
addPanel(panel):: self {
local parent = self,
_panelSlot:: self._panelSlot + 1,
_panels+: [{
slot: parent._panelSlot,
panel: panel,
}],
},
RUNTIME ERROR: max stack frames exceeded.
...
<anonymous>
lib/grafana/builder.libsonnet:(13:9)-(15:10) thunk <array_element>
lib/grafana/builder.libsonnet:19:29-35 object <anonymous>
lib/grafana/builder.libsonnet:19:15-37 thunk <array_element>
lib/grafana/builder.libsonnet:(7:24)-(20:6) object <anonymous>
During manifestation
My question
How can I modify variables (i.e. increment a counter) within a method, so that the modified variable is accessible in the next call of that method?
Upvotes: 0
Views: 872
Reputation: 3020
How can I modify variables (i.e. increment a counter) within a method, so that the modified variable is accessible in the next call of that method?
IIUC you can't really keep and mutate state in a way similar to other OOP languages.
You can approach this by mutating an object into a new one (with the modified/added data) by chaining calls that return the new object
Crafting an example below:
local Array = {
array: [],
count: 0,
addElem(e):: self {
// Overload (mutate) this object
array+: [e],
count+: 1,
}, // return mutated object
};
// Below 4 lines are equal to
// Array.addElem('x').addElem('y').addElem('z'); but kinda more readable
local obj = Array
.addElem('x')
.addElem('y')
.addElem('z');
obj
$ jsonnet example1.jsonnet
{
"array": [
"x",
"y",
"z"
],
"count": 3
}
Applying above approach to your code:
local Class = {
Row(title, height):: {
local this = self, // clamp a reference to the current self
_panelSlot: 0,
_panels: [],
_height: height,
title: title,
// addPanel() changes it-`self` to return a mutated Row
addPanel(panel):: self {
_panelSlot+: 1,
_panels+: [{
slot: this._panelSlot,
panel: panel,
}],
},
},
};
local obj = Class
.Row('Title', 42)
.addPanel('Foo')
.addPanel('Bar');
obj
$ jsonnet example2.jsonnet
{
"_height": 42,
"_panelSlot": 2,
"_panels": [
{
"panel": "Foo",
"slot": 0
},
{
"panel": "Bar",
"slot": 1
}
],
"title": "Title"
}
BTW would recommend taking a look at grafonnet-lib in case you didn't already.
Upvotes: 1