什么是柯里化?如何实现?

在函数式编程中,柯里化是一种将多参数函数转化为一系列单参数函数的技术。它得名于数学家哈斯凯尔·柯里。简单来说,它让一个函数每次只接收一个参数,并返回一个新函数去接收下一个参数,直到所有参数都被提供,最终执行原函数并返回结果。这种技术能增强函数的组合性和复用性。

柯里化的核心概念

普通函数一次调用需要提供所有参数。而柯里化后的函数允许你分步、分批地提供参数,每次接收一部分参数后,返回一个记住了这些参数的新函数。

// 普通加法函数
function add(a, b, c) {
  return a + b + c;
}

// 柯里化后的加法函数
function curriedAdd(a) {
  return function(b) {
    return function(c) {
      return a + b + c;
    };
  };
}
console.log(curriedAdd(1)(2)(3)); // 6
const addOne = curriedAdd(1);
const addOneAndTwo = addOne(2);
console.log(addOneAndTwo(3)); // 6

柯里化过程创建了一系列的闭包,每个返回的函数都记住了之前传入的参数。这使得我们可以轻松创建一些预设了部分参数的专用函数,例如上面预先设定第一个加数为1的addOne函数。

实现一个通用柯里化函数

手动为每个函数编写嵌套返回显然不现实。我们可以编写一个通用工具函数,它能将任意函数进行柯里化。

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

// 使用
function multiply(a, b, c) {
  return a * b * c;
}
const curriedMultiply = curry(multiply);
console.log(curriedMultiply(2)(3)(4)); // 24
const double = curriedMultiply(2);
console.log(double(5)(10)); // 100

这个curry函数检查当前收集的参数数量是否达到了原函数fn定义的长度(fn.length)。如果够了,就执行原函数;如果不够,就返回一个新函数,继续收集剩余参数。

柯里化的实际应用价值

柯里化最主要的优势在于参数复用和延迟执行。它能帮助我们基于一个通用函数,创建出许多更具体、更专注的函数。

const prefix = curry((logLevel, message) => {
  console.log(`[${logLevel}] ${message}`);
});
const logInfo = prefix('INFO');
const logError = prefix('ERROR');

logInfo('系统启动');
logError('发生未知错误');

这里,通过柯里化,我们从通用的prefix函数创建出了专用的logInfologError函数,它们已经固定了日志级别这个参数,使用时只需要关心消息内容。

柯里化是函数式编程中的一个重要模式,它与函数组合紧密相关。需要注意的是,JavaScript中的柯里化通常指的是“部分应用”的变体,并非严格的每次只接受一个参数。在实际开发中,它对于创建可配置的实用函数、提高代码的模块化程度非常有帮助。

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容