在Ramda中使事情毫无意义

时间:2018-06-29 15:22:15

标签: javascript ramda.js pointfree

我现在正在学习JS库Ramda。而且似乎有一种模式我无法正确解决。例如,我有此代码。

const filterPayments = filter => payments =>
  r.filter(
    r.allPass([
      typePred(filter),
      amountPred(filter),
      accountPred(filter),
      currencyPred(filter)
    ]),
    payments
  );

现在这似乎是一种情况,在此情况下,我并不是不愿意让它变得毫无意义。我似乎找不到正确的方法。

此外,我在使像这样的逻辑功能完全可用且没有点数方面遇到麻烦:

const amountPred = filter => p =>
  r.and(p.betrag >= filter.amount.min, p.betrag <= filter.amount.max);

也许有人可以为我指明正确的方向或提供一些指导?

2 个答案:

答案 0 :(得分:2)

我将提供的指导是坚持您当前拥有的:)

我可以向您展示一个示例,说明您所拥有内容的无点翻译是什么样子,尽管所得到的代码非常可怕,而且仅对一次精神体操有益。

首先,payments出现在函数表达式两边的最终位置,因此我们可以简单地将其删除。

const filterPayments = filter =>
  R.filter(
    R.allPass([
      typePred(filter),
      amountPred(filter),
      accountPred(filter),
      currencyPred(filter)
    ]));

接下来,我们可以看一下传递给R.allPass的函数列表

R.allPass(R.map(p => p(filter), [typePred, amountPred, accountPred, currencyPred]))

现在,我们可以通过翻转filter将其推到末尾来开始删除R.map自变量。

R.allPass(R.flip(R.map)([typePred, amountPred, accountPred, currencyPred])(p => p(filter))

现在让我们制作filterp => p(filter)的参数,而不是关闭它,使其成为:

R.allPass(R.flip(R.map)
  ([typePred, amountPred, accountPred, currencyPred])
  (R.applyTo(filter)))

现在h(g(f(a)))开始成形,我们可以使用R.pipeR.composeR.o等将其转换为无点。

const filterPayments = R.compose(
  R.filter,
  R.allPass,
  R.flip(R.map)([typePred, amountPred__, accountPred, currencyPred]),
  R.unary(R.applyTo) // R.unary is needed here to tell Ramda only to expect the first argument in this composition
)

这为我们提供了一个功能,该功能现在应该等效于您的filterPayments(无点形式)。

您的amountPred示例变得更加复杂,我想您以后会同意,您已经拥有的是两者之间更好的选择。

同样,我们首先尝试将参数推到表达式每一边的末尾:

filter => p =>
  both(
    x => x >= filter.amount.min,
    x => x <= filter.amount.max
  )(p.betrag)

然后我们可以放下p

filter => R.o(
  both(
    x => x >= filter.amount.min,
    x => x <= filter.amount.max
  ),
  prop('betrag'))

传递给both的函数也可以换出:

filter => R.o(
  both(
    R.flip(R.gte)(filter.amount.min),
    R.flip(R.lte)(filter.amount.max)
  ),
  prop('betrag'))

现在要解决filter,我们可以使用R.converge将相同的参数传递给多个函数,然后将每个函数的结果合并在一起。

filter => R.o(
  R.converge(both, [
    f => R.flip(R.gte)(R.path(['amount', 'min'], f),
    f => R.flip(R.lte)(R.path(['amount', 'max'], f)
  ])(filter),
  prop('betrag'))

现在f处于结束位置,因此可以按组成将其删除:

filter => R.o(
  R.converge(both, [
    R.o(R.flip(R.gte), R.path(['amount', 'min'])),
    R.o(R.flip(R.lte), R.path(['amount', 'max']))
  ])(filter),
  prop('betrag'))

最后将filter弄得很混乱,涉及到翻转合成函数。

filter => R.o(
  R.flip(R.o)(R.prop('betrag')),
  R.converge(both, [
    R.o(R.flip(R.gte), R.path(['amount', 'min'])),
    R.o(R.flip(R.lte), R.path(['amount', 'max']))
  ])
)(filter)

最后...

const amountPred = R.o(
  R.flip(R.o)(R.prop('betrag')),
  R.converge(both, [
    R.o(R.flip(R.gte), R.path(['amount', 'min'])),
    R.o(R.flip(R.lte), R.path(['amount', 'max']))
  ])
)

...将其与您的原始内容进行比较,我知道我更喜欢阅读以下内容:

const amountPred = filter => p =>
  p.betrag >= filter.amount.min && p.betrag <= filter.amount.max

答案 1 :(得分:0)

我已经开始做和Scott Christopher一样的工作,并且将主要功能重构为无点,从一开始就知道我的建议几乎肯定不会为此而烦扰。我找到了我的无点版本,它比我预期的要简单。在开始谓词之前,我曾想过看看Scott的解决方案。

他做了我会做的很多事情,而且可能比我做的更好。当然,他以类似的建议告终。我总是试图建议人们不要出于无聊而迷恋。当它使您的代码更简洁易懂时,请使用它。不用时不要使用它。

我什么都不会回答,只是我最终得到了一个更好的主函数无点版本,并且想考虑一下:

const filterPayments = pipe(
  juxt([typePred, amountPred, accountPred, currencyPred]),
  allPass,
  filter
)

尽管这很干净,但我认为它的可读性不如您的原著,因此我不建议您这样做。但是,如果您真的想要无积分,那就有可能。