使用 ramda 组合镜头

composing lenses using ramda

我正在尝试查询嵌套对象的内容 coor

const data = [ 
   [ [{geo: {coor: [1,2]}}, {geo: {coor: [4,5]}}], {} ], 
   [ [{geo: {coor: [8,2]}}, {geo: {coor: [9,5]}}], {} ]
 ]

结果应该是:

[[[1, 2], [4, 5]], [[8, 2], [9, 5]]]

我使用以下代码得到这个结果:

const viewLens = R.view(R.lensPath(['geo', 'coor']))
R.map(R.map(viewLens), R.map(R.view(lensIndex(0)), data))

但我想组成一个镜头,可以用来映射 data,类似于:

const coorLens = R.compose(R.lensIndex(0), ..., R.lensPath(['geo', 'coor']))

可以像这样使用:

R.map(coorLens, data)

有人知道如何构造这样的镜头吗?

谢谢!

有一个 mapped setter 的概念可用于更新透镜结构中仿函数的值,尽管这只能与 over/[= 一起使用16=] 而不是 view(即如何从只能由 map 修改的内容中获取元素?)

还有一种可穿越光学系统的概念,它可以关注许多元素,而不仅仅是一个元素。这使您既可以更新焦点下的所有元素,也可以说明您希望如何将许多元素组合到一个结果中,您还可以查看它们。但是,这不会为您提供完全相同的结构,因为所有聚焦元素将组合在一起,这与示例中的列表列表不同。

Ramda 本身不提供此功能,但可以在 ramda-lens 库中找到它。

const RL = ramdaLens

const data = [ 
  [ [{geo: {coor: [1,2]}}, {geo: {coor: [4,5]}}], {} ], 
  [ [{geo: {coor: [8,2]}}, {geo: {coor: [9,5]}}], {} ]
]

const coorLens = R.compose(
  RL.traversed,
  R.lensIndex(0),
  RL.traversed,
  R.lensPath(['geo', 'coor'])
)

console.log(
  "Combine all the focused elements in a list\n",
  RL.listOf(coorLens, data)
)

console.log(
  "Update all the focused elements\n",
  RL.over(coorLens, R.map(R.inc), data)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
<script src="https://wzrd.in/standalone/ramda-lens"></script>

我觉得值得指出的是,除非您通过组合镜头的能力在这里获得任何东西,或者同时查看和更新​​聚焦元素,否则避免使用可以说是更直接的功能组合的镜头可能会更简单,如下所示。

const data = [ 
  [ [{geo: {coor: [1,2]}}, {geo: {coor: [4,5]}}], {} ], 
  [ [{geo: {coor: [8,2]}}, {geo: {coor: [9,5]}}], {} ]
]

const fn = R.map(R.pipe(R.head, R.map(R.path(['geo', 'coor']))))

console.log(
  "Without lenses\n",
  fn(data)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>