У меня есть структура данных, которую я называю «spec», которая выглядит так:
const spec = {
command: {
name: 'name',
description: 'description',
alias: 'alias',
arguments: '_children/Arguments'
},
arguments: {
name: 'name',
alias: 'alias',
optional: 'optional',
description: 'description'
}
};
Таким образом, элементы внутри command и arguments являются свойствами, сопоставленными с путями. Лучшая иллюстрация этого - spec.command.arguments . Что мне нужно сделать, это перевести это в другой объект с той же формой, но пути преобразуются в линзы Ramda (используя R.lensPath).
Итак, концептуально это переводится примерно так:
const spec = {
command: {
name: lens('name'),
description: lens('description'),
alias: lens('alias'),
arguments: lens('_children/Arguments')
},
arguments: {
name: lens('name'),
alias: lens('alias'),
optional: lens('optional'),
description: lens('description')
}
};
Вышесказанное не следует понимать буквально, это псевдоструктура. Например, lens ('_ children / Arguments') просто представляет объектив, созданный с использованием Ramda lensPath.
Так вот мой код:
const spec = {
command: {
name: 'name',
description: 'description',
alias: 'alias',
arguments: '_children/Arguments'
},
arguments: {
name: 'name',
alias: 'alias',
optional: 'optional',
description: 'description'
}
};
function lensify (spec) {
const result = R.pipe(
R.toPairs,
R.reduce((acc, pair) => {
const field = pair[0];
const path = pair[1];
const lens = R.compose(
R.lensPath,
R.split('/')
)(path);
acc[field] = lens; // Is there something wrong with this, if so what?
return acc;
}, { dummy: '***' }) // list of pairs passed as last param here
)(spec);
// The following log should show entries for 'name', 'description', 'alias' ...
console.log(`+++ lensify RESULT: ${JSON.stringify(result)}`);
return result;
}
function makeLenses (spec) {
const result = {
command: lensify(spec.command),
arguments: lensify(spec.arguments)
};
return result;
}
makeLenses(spec);
Ключевая точка отказа, я думаю, находится внутри функции редуктора, которая возвращает обновленный аккумулятор ( acc [field] = lens; ). По некоторым причинам, которые я не могу понять, это назначение теряется, и аккумулятор не заполняется правильно на каждой итерации. Как видно из примера кода, начальное значение, передаваемое в lower, является объектом с одним свойством dummy . Результатом уменьшения является неверно только это единственное фиктивное значение, а не все поля с соответствующими линзами Ramda.
Однако, что действительно испечет вашу лапшу, так это то, что один и тот же код, запущенный в repda Ramda, демонстрирует другое поведение, этот код можно увидеть в ответе по адресу: Код Ramda
Я использую узел версии 10.13.0
Результат, который дает код Repl, таков:
{
'arguments': {
'alias': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
},
'description': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
},
'dummy': '***',
'name': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
},
'optional': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
}
},
'command': {
'alias': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
},
'arguments': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
},
'description': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
},
'dummy': '***',
'name': function (r) {
return function (e) {
return z(function (t) {
return n(t, e)
}, r(t(e)))
}
}
}
}
Как видите, результат выглядит несколько сложным, поскольку значения каждого свойства - это объектив, созданный lensProp.
Это в отличие от следующего (обратите внимание, что порядок команд и аргументов поменялся местами, но это не должно быть значительным):
{
'command': {
'dummy': '***'
},
'arguments': {
'dummy': '***'
}
}
, который возвращается в моем модульном тесте.
Я потратил около 2 дней на это и теперь признал поражение, так что, надеюсь, кто-нибудь сможет пролить свет на это. Приветствия.