# 函数柯里化

柯里化(Currying)是一种关于函数的高阶技术。它不仅被用于 JavaScript,还被用于其他编程语言。

柯里化是一种函数的转换,它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。

柯里化不会调用函数。它只是对函数进行转换。

比如这个例子,我们创建一个辅助函数 curry(f),该函数将对两个参数的函数 f 执行柯里化

function (f) {
  return function(a) {
    return function(b) {
      return f(a,b)
    }
  }
}
function sum(a,b) {
  return a + b;
}
let curriedSum = curry(sum);
console.log(curriedSum(1)(2))

# 柯里化的目的是什么

例如,我们有一个用于格式化和输出信息的日志(logging)函数

function log(date, importance, message) {
  alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
}

我们将它柯里化,柯里化之后,log 仍正常运行:

log = _.curry(log);
log(new Date(), "DEBUG", "some debug"); // log(a, b, c)
log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)

现在我们可以固定其中一个参数,创建一个“偏函数(partial)”

// logNow 会是带有固定第一个参数的日志的偏函数
let logNow = log(new Date());
// 使用它
logNow("INFO", "message"); // [HH:mm] INFO message

我们可以更进一步,为当前的调试日志(debug log)提供便捷函数

let debugNow = logNow("DEBUG");
debugNow("message"); // [HH:mm] DEBUG message

所以:

  • 柯里化之后,我们没有丢失任何东西:log 依然可以被正常调用。
  • 我们可以轻松地生成偏函数,例如用于生成今天的日志的偏函数。

# 高级柯里化实现

下面这个简单的示例,实现了多参数函数的“高级”柯里化实现。它把接收多参的函数转化成可以逐个调用单个参数并返回接收剩下参数的函数

function curry(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      return func.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      }
    }
  };
}

# 总结

柯里化 是一种转换,将 f(a,b,c) 转换为可以被以 f(a)(b)(c) 的形式进行调用。

JavaScript 实现通常都保持该函数可以被正常调用,并且如果参数数量不足,则返回偏函数。

柯里化是偏函数的实现方式之一,柯里化让我们能够更容易地获取偏函数。