在 Ramda 中做一些无意义的事情
Making something point-free in Ramda
我现在正在学习 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);
也许有人可以指出正确的方向或提供一些指导?
我提供的指导是坚持你目前拥有的:)
我可以向您展示一个示例,说明您所拥有的内容的无点翻译可能是什么样子,尽管生成的代码读起来非常可怕,而且实际上只对心理体操有用。
首先,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))
现在让 filter
和参数 p => p(filter)
而不是关闭它,使它成为:
R.allPass(R.flip(R.map)
([typePred, amountPred, accountPred, currencyPred])
(R.applyTo(filter)))
现在开始形成像 h(g(f(a)))
的形状,我们可以使用 R.pipe
、R.compose
、R.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
我已经开始做与 Scott Christopher 所做的相同类型的工作,并将主要功能重构为 point-free,从一开始就知道我的建议几乎肯定是不要为 point-free 而烦恼这个。我找到了我的免积分版本,它比我预期的要简单。在开始谓词之前,我查看了 Scott 的解决方案。
他做了很多我会做的事情,而且可能比我做的更好。当然,他以类似的建议结尾。我总是试图建议人们不要迷恋无意义。当它使您的代码更清晰、更易于理解时使用它。不用的时候不要用。
我根本不会回答,除了我最终得到了一个更好的 main 函数的无点版本,并且想提供它以供考虑:
const filterPayments = pipe(
juxt([typePred, amountPred, accountPred, currencyPred]),
allPass,
filter
)
虽然这本书相当干净,但我认为它的可读性不如您的原文,因此我不推荐它。但是如果你真的想要免分,这个是有可能的。
我现在正在学习 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);
也许有人可以指出正确的方向或提供一些指导?
我提供的指导是坚持你目前拥有的:)
我可以向您展示一个示例,说明您所拥有的内容的无点翻译可能是什么样子,尽管生成的代码读起来非常可怕,而且实际上只对心理体操有用。
首先,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))
现在让 filter
和参数 p => p(filter)
而不是关闭它,使它成为:
R.allPass(R.flip(R.map)
([typePred, amountPred, accountPred, currencyPred])
(R.applyTo(filter)))
现在开始形成像 h(g(f(a)))
的形状,我们可以使用 R.pipe
、R.compose
、R.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
我已经开始做与 Scott Christopher 所做的相同类型的工作,并将主要功能重构为 point-free,从一开始就知道我的建议几乎肯定是不要为 point-free 而烦恼这个。我找到了我的免积分版本,它比我预期的要简单。在开始谓词之前,我查看了 Scott 的解决方案。
他做了很多我会做的事情,而且可能比我做的更好。当然,他以类似的建议结尾。我总是试图建议人们不要迷恋无意义。当它使您的代码更清晰、更易于理解时使用它。不用的时候不要用。
我根本不会回答,除了我最终得到了一个更好的 main 函数的无点版本,并且想提供它以供考虑:
const filterPayments = pipe(
juxt([typePred, amountPred, accountPred, currencyPred]),
allPass,
filter
)
虽然这本书相当干净,但我认为它的可读性不如您的原文,因此我不推荐它。但是如果你真的想要免分,这个是有可能的。