我是 Ramda 和函数式编程的新手,我想知道有人如何改进下面的代码或将其转换为点自由风格
const doc = {
passwordRecovery: {
requested: true,
expiresAt: new Date(Date.now() + 1000).toISOString(),
code: 'abc'
}
}
const req = {
password: '123',
passwordRecovery: {
code: 'abc'
}
}
const pathCode = R.path(['passwordRecovery', 'code'])
const isValidCode = R.curry(
(doc, req) => R.all(
R.hasPath(['passwordRecovery', 'code'], req),
R.pathEq(['passwordRecovery', 'requested'], true, doc),
R.compose(R.complement(R.isNil), pathCode)(doc),
R.equals(pathCode(req), pathCode(doc)),
R.pipe(
R.path(['passwordRecovery', 'expiresAt']),
Date.parse,
R.gte(R.__, Date.now()),
)(doc)
)
);
isValidCode(doc)(req)
最佳答案
一些建议:
避免混淆
不熟悉柯里化(Currying)的人经常会说同样的话:当你可以执行 add(1, 2)
时,为什么还要执行 add(1)(2)
呢?他们是对的。这个例子根本没有公正地描述柯里化(Currying)。
如果您的团队只是想熟悉函数式编程,请不要让他们感到不必要的困惑。如果您可以一次性提供所有参数,请执行以下操作:
isValidCode(doc, req); // not isValidCode(doc)(req);
不要为了使用 Ramda 而使用 Ramda
此:R.equals(pathCode(req), pathCode(doc))
与:pathCode(req) === pathCode(doc)
相同。
如果您确实想使用 Ramda,请考虑 eqBy
相反:
eqBy(pathCode, req, code);
Pointfree 并不是唯一的方法
这确实是一种有趣的函数编写方式,但它不能成为目标。假设您需要检查 a
是否等于 'foo'
并且 b
是否等于 'bar'
:
这个函数是无点函数吗:
const fn = useWith(and, [equals('foo'), equals('bar')]);
还有比这更好的吗:
const fn = (a, b) => a === 'foo' && b === 'bar';
?
all
是否正确调用?
根据文档,all
接受一个函数和一个列表:
all(x => x === 42)([41, 42, 43]);
除非我弄错了,否则您所做的就是使用每个函数调用的结果来调用 all
。例如
all(true, false, true, ...);
避免使用 __
占位符
gte(__, Date.now())
可以更改为 flip(gte)(Date.now())
保持一致
在一种情况下,您允许将路径设置为未定义
:
// true even for `{passwordRecovery: {code: undefined}}`
hasPath(['passwordRecovery', 'code'], req);
而在其他情况下你不需要:
compose(R.complement(R.isNil), pathCode)(doc)
保持一致可以实现这一点:
const notNil = complement(isNil);
both(pathSatisfies(notNil, pathCode), req, doc)
关于javascript - 您将如何重写这个多参数函数,最终实现点自由风格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57961717/