柯里化(Currying):把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数。
柯里化由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,它是 Moses Schnfinkel 和 Gottlob Frege 发明的。
柯里化的应用最为切底是纯函数编程语言Haskell ,Haskell 中还有很多思想对其他语言有着深刻影响,比如模式匹配、柯里化、函数式编程等。
Haskell 的代码:
multThree :: (Num a) => a -> a -> a -> a
multThree x y z = x * y * z
若执行mulThree 3 5 9
或((mulThree 3) 5) 9
, 首先,按照空格分隔,把3交给mulThree。 这返回一个返回函数的函数。 然后把5交给它,返回一个取一个参数并使之乘以15的函数。 最后把9交给这一函数,返回135。 这个函数的类型
也可以写作multThree :: (Num a) => a -> (a -> (a -> a))
,->前面的东西就是函数取的参数,后面的东西就是其返回值。 所以说,我们的函数取一个a,并返回一个类型为(Num a) => a -> (a -> a)
的函数,类似,这一函数返回一个取一个a,返回一个类型为(Num a) => a -> a
的函数。 而最后的这个函数就只取一个a并返回一个a。
即:((mulThree 3) 5) 9
mulThree 3 =>multThree 3 y z = 3 * y * z
mulThree 5 =>multThree 3 5 z = 3 * 5 * z
mulThree 9 =>multThree 3 5 9 = 3 * 5 * 9
下面来看看js中的柯里化:
代码:
function currying(fn, n) {
return function (m) {
return fn.call(this, m, n);
};
}
function tailFactorial(n, total) {
if (n === 1) return total;
return tailFactorial(n - 1, n * total);
}
const factorial = currying(tailFactorial, 1);
factorial(5) //
执行currying(tailFactorial, 1) 返回的函数是:
function tailFactorial(n, 1) {
if (n === 1) return total;
return tailFactorial(n - 1, n * 1);
}
本来需要传两个参数n、m,经过柯里化之后只需传一个参数,便可以求出n的阶乘。
这样做的好处是可以复用代码,通过设置 currying(fn, n)中的n值来得到不同的其实参数的函数。