关于柯里化
柯里化(Currying)把接受多个参数的函数变成单个参数的函数
比如我们有一个sum函数,接受三个参数
func sum(x, y, z int) int {
return x + y + z
}
改成接受单个变量
func curryingSum(x int) func(int) func(int) int {
return func(z int) func(int) int {
return func(y int) int {
return x + y + z
}
}
}
于是调用起来就从f(x, y, z)变为f(x)(y)(z)
sum(1, 2, 3)
curryingSum(1)(2)(3)
这样看起来性质很良好,只接受一个参数,返回一个输出。直觉告诉我们,接收单个变量的函数,比接收多个变量的函数有一些更加良好的性质。
但是go的curringSum函数要写返回值类型,看起来比较难受,用js来一版
const curryingAdd = function(x) {
return function(y) {
return function(z) {
return x + y + z
}
}
}
scheme版本的看起来也跟js差不多
(define (currySum f)
(lambda(x)
(labmda(y)
(lambda(z)
(f x y z)))))
对n个变量的Curry函数很容易实现
(define (curry n f)
(if (= n 1) f
(curry
(- n 1)
(lambda s (lambda (a) (apply f (append s (list a))))))))
js版本:
function curry(fn){
var args = Array.prototype.slice.call(arguments,1);
return function(){
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);
}
}
类似的,我们可以实现反柯里化,说明多变量函数和单变量单返回函数可以相互转换
(define ((uncurry f) . t)
(if (null? t)
f
(apply (uncurry (f (car t)))
(cdr t))))
那柯里化有什么用呢,可以用来实现多参数函数(逃
在手搓自制scheme中,我们已经实现了有一个接收一个输入、返回一个输出的函数,那么可以通过柯里化实现一个接收多参数的函数。
link
柯里化