Совет, который я предлагаю, - придерживаться того, что у вас есть:)
Я могу показать вам пример того, на что могут быть похожи бессмысленные переводы того, что у вас там есть, хотя полученный код довольно ужасен для чтения и действительно хорош только для сеанса умственной гимнастики.
Прежде всего, 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