Skip to content

Instantly share code, notes, and snippets.

@mkmik
Created March 4, 2019 17:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkmik/aa7f495541e4c883ad2426615d6e3525 to your computer and use it in GitHub Desktop.
Save mkmik/aa7f495541e4c883ad2426615d6e3525 to your computer and use it in GitHub Desktop.
// mapObjects applies func on every object in a tree.
local mapObjects(obj, func=function(n, o) {}) = {
[n]+: mapObjects(obj[n], func) + func(n, obj[n])
for n in std.objectFields(obj)
if std.isObject(obj[n])
};
// deepMerge applies a patch to every object matching a predicate.
local deepMerge(obj, patch, pred=std.isObject) = obj + mapObjects(obj, function(n, o) if pred(o) then patch else {});
/// Example
local tree = {
universe: {
life: {
kind: 'foo',
everything: self.b * $.params.mult,
b:: 0,
x:: 1,
rec: {
kind: 'foo',
x:: 22,
},
},
},
params:: {
mult: 1,
},
};
local patch = {
b: 20 + self.x,
};
local parentPatch = {
params+: { mult: 2 },
};
local isFoo(o) = std.objectHas(o, 'kind') && o.kind == 'foo';
// implement deepMerge 'manually' for this particular object tree:
local manual(obj, patch) = obj {
universe+: {
life+: patch {
rec+: patch,
},
},
};
{
manual: manual(tree, patch) + parentPatch,
merge: deepMerge(tree, patch, isFoo) + parentPatch,
std: tree + std.mapWithKey(function(n, o) if isFoo(o) then o + patch else o, tree) + parentPatch,
eq: std.assertEqual(self.manual, self.merge),
neq: if self.manual == self.std then error 'mapWithKey should be broken' else true,
}
{
"eq": true,
"manual": {
"universe": {
"life": {
"everything": 42,
"kind": "foo",
"rec": {
"b": 42,
"kind": "foo"
}
}
}
},
"merge": {
"universe": {
"life": {
"everything": 42,
"kind": "foo",
"rec": {
"b": 42,
"kind": "foo"
}
}
}
},
"neq": true,
"std": {
"universe": {
"life": {
"everything": 0,
"kind": "foo",
"rec": {
"kind": "foo"
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment