在 Ramda 中两次调用 Arg

Calling an Arg twice in Ramda

我正在使用 Ramda 构建一个简单的应用程序。

我 运行 遇到一个功能组合问题,我不确定如何在不创建看似不必要的荒谬功能的情况下解决这个问题。

场景:

我有一个对象作为参数传递。这个对象有两个属性,还有一些与问题无关的东西,除了我不想改变它的状态:

{locCode :<string>, LocationList : [<Location>], someOtherParams : ...  } 

我有一个 arg 函数可以将 locCode 转换为位置: fetchLocByCode

我想要的结果是获取 locCode 值,将其传递给 fetchLocByCode,将结果附加到 LocationList,然后 return 一个新对象新的 LocationList 没有触及对象上的任何其他内容。

类似于:

(Param)=>{
Param.LocationList.push(fetchLocByCode(Param.locCode));
return Param;
}

我最后写的东西看起来非常荒谬,让我相信我做了一些非常错误的事情:

const locListLens = R.lens(R.prop('LocationList'),R.assoc('LocationList'))
const appendLocList = (i)=>R.compose(R.over(locListLens),R.append,fetchLocByCode,R.prop('locCode'))(i)(i)

这个解决方案 'works' 但似乎我错过了一些基本思想。

有人愿意提出一种更 'canonical' 的方法来解决这种情况吗?

让我们从您的初始版本开始:

Param => {
  Param.LocationList.push(fetchLocByCode(Param.locCode));
  return Param;
}

非常希望不需要突变。让我们删除它:

Param =>
  R.assoc('LocationList',
          R.append(fetchLocByCode(Param.locCode), Param.LocationList),
          Param)

我们可以使用镜头来避免访问 LocationList 属性 两次:

Param =>
  R.over(R.lensProp('LocationList'),
         R.append(fetchLocByCode(Param.locCode)),
         Param)

我们可以完全摆脱 Param 吗?让我们从使用 R.converge:

开始
R.converge(R.over(R.lensProp('LocationList')),
           [Param => R.append(fetchLocByCode(Param.locCode)),
            R.identity])

让我们使用R.compose从第一个分支函数中删除Param

R.converge(R.over(R.lensProp('LocationList')),
           [R.compose(R.append, fetchLocByCode, R.prop('locCode')),
            R.identity])

任何时候你发现自己在编写 R.converge(f, [g, R.identity]) 你已经发现了 S 组合器的用途!

S.S(R.flip(R.over(R.lensProp('LocationList'))),
    R.compose(R.append, fetchLocByCode, R.prop('locCode')))

虽然这很简洁,但我认为 R.assoc 版本很好。未来的读者不会喜欢必须理解 S.S(R.flip(R.over(R.lensProp。 ;)