在参数顺序错误的地方自由点

point free where arguments are in the wrong order

我想使用 Ramda 的标准函数集编写一个函数,给定一个字典和一个键,它将增加键的值。例子

fn('foo', {}) // => {foo: 1}
fn('foo', {foo: 1}) // => {foo: 2}

我已经很接近了,但我缺少正确咖喱的方法。

我有一个方法需要一个键和一个对象,return还有一个:

// count :: Any -> Number
var count = R.compose(R.inc, R.defaultTo(0))

// countProp :: String -> Object -> Number
var countProp = R.curry(R.compose(count, (R.prop(R.__))))

countProp('foo', {foo:1}) // 2
countProp('foo', {}) // 1

现在我想return一个新的数据结构

// accum :: String -> Object -> Object
var accum = R.curry(function(key, obj){
  return R.assoc(key, countProp(key, obj), obj)
})

accum('foo', {foo: 1}) // => {foo: 2}

但问题是,为了免除这一点,我必须弄清楚如何获取函数设置中的值,以便以正确的顺序进行柯里化。我究竟做错了什么?我应该以不同的方式设置此功能吗?我试图设置它,以便两个依赖函数都先获取密钥,然后再获取对象,但我遗漏了一些东西。我应该为此考虑一个特定的 Functor 吗?

谢谢!

您可以使用 R.lens:

const fooLens = R.lens(R.prop('foo'), R.assoc('foo'));

fooLens.map(R.inc, {foo: 1, bar: 2});  // => {foo: 2, bar: 2}
fooLens.map(R.inc, {foo: 2, bar: 2});  // => {foo: 3, bar: 2}
fooLens.map(R.inc, {foo: 3, bar: 2});  // => {foo: 4, bar: 2}

Lenses 使得创建一系列值成为可能,而不会通过改变它来破坏后继值的完整性。

几点:

首先,如果@davidchambers 的解决方案满足您的需求,那就太好了。下个版本的 Ramda 发布并添加 lensProp 时会更好,这将使

var fooLens = R.lensProp('foo');
fooLens.map(R.inc, {foo: 1, bar: 2});  // => {foo: 2, bar: 2}

第二,你的原版功能和任一镜头版本有区别:

accum('foo', {bar: 1}); //=> {"bar":1,"foo":1}
fooLens.map(R.inc, {bar: 1}); //=> {"bar":1,"foo":null}

第三,尽管如此,如果您有兴趣确定如何以无积分的方式包装您的函数,Ramda 有几个函数可以提供帮助。有一个辅助函数 nthArg which does nothing but return a function that return the nth argument of the outer function in which it's called. Then there are several functions that act as extended versions of compose including useWith and converge.

您可以像这样使用它们:

var accum = R.converge(R.assoc, R.nthArg(0), countProp, R.nthArg(1));
accum('foo', {foo: 1, bar: 2});  // => {foo: 2, bar: 2}
accum('foo', {bar: 2});  // => {foo: 1, bar: 2}

在此代码中,converge 将参数(keyobj)传递给作为参数传递的每个函数(第一个除外),然后传递结果每一个都是第一个函数。


Finally,尽管这展示了一种无积分编写此代码的方法,而且它最终并不太可怕,但可以说它不如你的早期版本那么清晰t点免。我喜欢无积分代码。但有时我们会迷恋它,无缘无故地使代码点免费。如果您最终无法使用 lens 版本,您可能需要仔细考虑免积分解决方案是否真的比替代方案更清晰。