1 javascript functional-programming
我是 JavaScript 的新手,我正在尝试编写函数式编程来计算一个数字是否为奇数 (isOdd)。我不明白为什么当我连续两次调用 isOdd() 时会得到 true 和 0 或 false 和 1。
这是我的代码:
var mod = m => {return number => {return number % m }}
var eq = number1 => {return number2 => {return number1 === number2}}
var combine = (...fns) => { return arg => {for(let fn of fns.reverse()) arg = fn(arg); return arg;}}
var eq1 = eq(1)
var mod2 = mod(2)
var isOdd = combine(eq1, mod2)
mod2(4) -----> returns 0
mod2(3) -----> returns 1
eq1(1) -----> returns true
eq1(2) -----> returns false
isOdd(1) returns true
isOdd(1) returns 1 (what??)
Run Code Online (Sandbox Code Playgroud)
我无法理解我错过了什么或出了什么问题。我在大多数浏览器中测试了这段代码。
不胜感激,如果有人可以详细解释。
我可以再次包装 isOdd 并有类似的东西
isOdd = (number) => {return Boolean(combine(eq1, mod2))}
Run Code Online (Sandbox Code Playgroud)
每次都返回布尔值。但我想首先了解我错过了什么/
Array.prototype.reversefns原地反转数组。你打电话.reverse的fns ,每次你打电话isOdd,即使你在传递功能的固定参数列表combine 一次。该列表combine在每次调用isOdd(1).
换句话说,您的第一次isOdd(1)调用会记住fns原始combine(eq1, mod2)调用的数组。fns是[ eq1, mod2 ]。然后你调用fns.reverse()迭代它;但这会变异 fns为[ mod2, eq1 ]. 你得到了正确的结果,因为你想以相反的顺序调用函数。结果调用是eq1(mod2(1)) === eq1(1) === true。
在你的第二个isOdd(1)电话,然而,fns是仍然记得,它仍然具有反转的[ mod2, eq1 ]价值,因为它的范围combine,那么另一个isOdd调用不会重置最初传递fns。第二个isOdd调用再次反转这个数组,因为fns.reverse在isOdd. 结果调用是mod2(eq1(1)) === mod2(true) === 1(因为true % 2被强制转换为1 % 2)。
一个工作函数看起来像这样:
const combine = (...fns) => {
const reversedFns = fns.reverse();
return (arg) => {
for(let fn of reversedFns){
arg = fn(arg);
}
return arg;
};
};
Run Code Online (Sandbox Code Playgroud)
一种更简单的方法使用Array.prototype.reduceRight:
const combine = (...fns) => (arg) => fns.reduceRight((result, fn) => fn(result), arg);
Run Code Online (Sandbox Code Playgroud)
由于您想根据从右到左的列表将多个操作聚合到单个结果中,因此reduceRight这是一个完美的方法。您从 开始arg,从右到左遍历函数列表,然后用 调用当前函数arg,这将成为arg下一个函数的新函数。返回最终结果。所有这些都被代码捕获fns.reduceRight((result, fn) => fn(result), arg)。