如果我想编写一系列函数,我可以使用compose
,这将允许我定义一系列函数,将一个或多个参数传递给第一个,然后返回第一个值传递给第二个,第二个的返回值传递给第三个,依此类推......
compose(f3, f2, f1)(value);
相当于:
f3(f2(f1(value)))
但是,如果我想用value
调用所有三个函数怎么办?
我的用例是我有一系列功能来验证一段数据。在每种情况下,如果值有效,函数会抛出无效的错误。我需要以这样的方式组合这些验证函数:传入一个值将导致每个函数按顺序调用值。有效:
f1(value);
f2(value);
f3(value);
// Do something now we are sure the value is valid.
使用ramda提供的函数我能看到的唯一方法是使用逻辑运算符来防止值返回false时出现短路:
const f1 = (v) => console.log(`f1 called with '${v}'`);
const f2 = (v) => console.log(`f2 called with '${v}'`);
const f3 = (v) => console.log(`f3 called with '${v}'`);
const callAll = compose(complement, anyPass);
callAll([f1, f2, f3])('x');
然而,这感觉就像滥用anyPass
一样。这是实现我想要的最合适的方式吗?
答案 0 :(得分:3)
但是,如果我想用值调用所有三个函数怎么办?
在一个值上运行多个函数的函数称为R.converge。
R.converge(
() => {},
[f1, f2, f3],
)('x');
第二个参数是一个函数数组。价值(在这种情况下' x')按顺序投入其中。
然而,在此之后,R.converge获取f1,f2,f3的返回值,并将它们作为第一个参数的参数抛出。你不需要R.converge的那部分,因为你没有对返回值做任何事情,所以你可以使用一个什么都不做的函数。
因此callAll可以写成:
const callAll =
R.converge(() => {});
执行如下:
callAll([f1, f2, f3])('x');
或未发现:
const callAll =
R.uncurryN(2, R.converge(() => {}));
callAll([f1, f2, f3], 'x');
答案 1 :(得分:2)
有效地:
f1(value); f2(value); f3(value);
每当你在代码中看到一个分号时,你知道你没有在功能上进行编程但是正在执行副作用: - )
不要这样做。最简单的方法确实是使用anyPass
,但让验证函数返回布尔值而不是抛出异常。
如果您需要收回错误消息,请使用Either
数据类型和traverse
:
const f1 = (v) => true ? Either.right("it's fine") : Either.left("oops");
const f2 = (v) => false? Either.right("it's fine") : Either.left("oops");
const f3 = (v) => true ? Either.right("it's fine") : Either.left("oops");
traverse(Either.of, R.apply('x'), [f1, f2, f3]); // Left("oops")
答案 2 :(得分:1)
如果将函数视为monad,则可以编写副作用。这是一个香草Javascript草图,但你也可以用Ramda表达它:
const chain = f => g => x => f(g(x)) (x);
const of = x => y => x;
const id = x => x;
const yourFun = x => y => y;
const fold = (f, acc) => xs => xs.reduce((acc_, x) => f(acc_) (x), acc);
const comp = f => g => x => f(g(x));
const compn = (...fs) => fold(comp, id) (fs);
const f1 = x => {console.log(`f1 called with ${x}`)}
const f2 = x => {console.log(`f2 called with ${x}`)}
const f3 = x => {console.log(`f3 called with ${x}`)}
compn(
chain(yourFun) (f3),
chain(yourFun) (f2),
chain(yourFun) (f1)
) ("x");

现在yourFun
忽略了第一个参数。您可能希望将其替换为对您的案例更有用的内容。
请注意,这不仅仅是一种教育活动,也不是一种正确的方法。我想告诉你monad如何用于组合带效果的计算。
答案 3 :(得分:1)
通过让验证函数返回布尔值并使用@ Service
public class Class1
{
/% Method 1 %/
/% Method 2 %/
/% Method 3 %/
/% Method 4 %/
}
:
public class Class2
{
@ Autowired
private Class1 class1;
/% class1.Method1() %/
/% class1.Method1() %/
.
.
.
}
工作小提琴here。