我正在尝试编写返回镜头的函数,以生产新镜头,并以无点风格进行操作。

这可能是一个关于函数组合的更普遍的问题。镜头只是一个案例研究。我对镜头不感兴趣,但我想知道如何以无点的方式组合这些功能的一般模式。

const obj = {a: {x: 0}, b: {x: 42}};

// this won't work, but I want it to work
const pointFreeComposedLens = R.compose(R.lensProp, R.lensProp('x'));
R.view(pointFreeComposedLens('a'), obj); // returns 'undefined'

// this works
const pointyComposedLens = key => R.compose(R.lensProp(key), R.lensProp('x'));
R.view(pointyComposedLens('a'), obj); // returns '0'

组合函数的模式是什么,这样我就不需要继续重写组合管道中第一个函数的参数?

对于一个令人震惊的例子:
const deepLens = (a, b, c) => R.lensPath([a, b, c]);

// This works, but is tedious & verbose
const extraDeep = (a, b, c, x) => R.compose(deepLens(a,b,c), R.lensProp(x));
const gammaDeep = (a, b, c, y) => R.compose(deepLens(a,b,c), R.lensProp(y));

// Doesn't work, but it would be nicer to write:
const extraDeep = x => R.compose(deepLens, R.lensProp(x));

// and call it like so:
R.view(extraDeep('a','b','c','x'), obj);

最佳答案

我知道您只是将镜头视为示例,但这里有一种方法可以让您获得我认为您想要的行为。

const {lensPath, compose, lens, view} = R

const deepLens = (a, b, c) => lensPath([a, b, c]);
const deeper = (lens, ...args) => compose(lens, lensPath(args))

const cLens = deepLens('a', 'b', 'c')
const obj =  {a: {b: { c: {d: 1, e: 2, f: {g: 3, h: 4, i: {j: 5, k: 6}}}}}}

console.log(view(cLens, obj)) //=> {d: 1, e: 2, f: {g: 3, h: 4, i: {j: 5, k: 6}}}
console.log(view(deeper(cLens, 'f', 'g'), obj)) //=> 3

const fLens = deeper(cLens, 'f')

console.log(view (fLens, obj)) //=> {g: 3, h: 4, i: {j: 5, k: 6}}

const jLens = deeper(cLens, 'f', 'i', 'j')
// or jLens = deeper(fLens, 'i', 'j')

console.log(view(jLens, obj)) //=> 5
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>


至于更广泛的构图问题,镜头通常是像 Ramda 这样的库的特例,因为构图的顺序与通常预期的相反。 (技术原因太多,这里就不赘述了。)

但这就是为什么这不起作用:



Ramda 确实允许合成链中的第一个函数(在 compose 最右边,在 pipe 最左边接收额外的参数。但是当合成顺序与镜头合成相反时,它不会做你可能喜欢的事情。

因此,如果您在其他上下文中遇到类似的构图问题,请提出一个单独的问题。我很想知道你在找什么。

关于javascript - Ramda.js 中镜头的无点组合,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54202899/

10-12 15:48