定义
函数柯里化指把一个接收多个参数的函数转换成接收单一参数的函数,并返回一个新函数以接收剩余参数,直到所有参数齐备后返回结果[1]。以取两个参数的加法函数为例,柯里化后变为先接收第一个参数并返回一个函数,该函数再接收第二个参数并求和[4]。
从调用形式上看,原本写作 $f(a,b,c)$ 的调用被改写成 $f(a)(b)(c)$ 的链式调用[5]。柯里化与偏函数应用密切相关但并不等同:偏函数应用强调固定任意个参数后返回一个更小元数的函数,柯里化强调把函数逐步变为一元函数[6]。
原理
柯里化的实现依赖两个语言特性:函数可以作为参数传入、函数可以作为返回值,以及闭包对中间参数的保存[7]。每次调用只传入一个参数,被传入的参数由闭包留存,尚未满足参数个数的调用返回新的函数,参数个数满足原函数形参数量时才真正执行原函数[8]。
从类型角度看,柯里化在类型 $((A \times B) \to C)$ 与 $A \to (B \to C)$ 之间建立了自然的一一对应,因此二元以上的函数可以通过归纳方式逐层柯里化[3]。函数类型箭头通常被视为右结合,函数应用被视为左结合,$f\ a\ b$ 等价于 $(f\ a)\ b$[2]。
其逆变换称为反柯里化(Uncurrying),它把返回函数的函数还原为一次性接收全部参数的函数,可视为去函数化的一种形式[2]。
发展历程
柯里化的思想最早由戈特洛布·弗雷格提出,随后由摩西·舍恩芬克尔加以发展,哈斯克尔·柯里作了进一步研究[3]。因此也有人主张,以舍恩芬克尔命名这一变换更为贴切[2]。
「柯里化」这一名称由克里斯托弗·斯特雷奇于 1967 年提出,用以向逻辑学家哈斯克尔·柯里致敬[2]。在理论计算机科学中,柯里化提供了在只接受单一参数的 Lambda 演算这类简单模型中研究多参数函数的方法[1]。
柯里化最一般的严格表述建立在闭笛卡尔范畴之上,它与证明与程序之间的柯里-霍华德对应关系的推广相关[3]。在编程语言层面,ML 与 Haskell 几乎总是以柯里化函数来实现多参数函数,所有函数都只带一个参数[1]。
应用
柯里化常用于参数复用:把重复出现的参数先固定下来,生成只接受剩余参数的新函数,减少重复书写[9]。以字符串替换为例,对接收两个参数与一个字符串的函数先行柯里化,可以派生出分别把空白替换为逗号、替换为短横线的多个专用函数[10]。
柯里化也是函数组合的基础。把多元函数化为单值函数后,可以借助 compose 之类的组合函数把多个小函数串成一条从右向左的流水线,部分函数库还提供方向相反的 pipe[10]。
在 JavaScript 中,柯里化可用于事件绑定的兼容封装,使浏览器能力判断只执行一次,并借此实现提前返回与延迟执行[9]。函数原生的 bind 方法同样具有柯里化特征:它设定执行上下文并把其余参数预先绑定,返回一个新函数而不立即执行[7]。部分工具库如 Lodash、Ramda 也提供了柯里化工具函数,其中多数多于一个参数的方法默认即被柯里化[11]。
局限
柯里化的收益主要体现在函数组合场景,对普通函数调用而言并无明显优势[6]。手工书写柯里化需要逐层嵌套,参数增多时嵌套层数随之增加,代码可读性与可扩展性都会下降,因此通常借助通用的 curry 工具函数或函数库处理[9]。
从执行效率看,柯里化函数需要不断创建闭包与中间函数,带来额外的开销,因此在多数函数调用中,非柯里化形式在效率上更受偏好[2]。
此外,柯里化严格限定每次只接收一个参数,它不能代替偏函数应用:固定任意个参数、一次传入多个参数再返回较小元数函数的做法属于偏函数应用,二者不应混为一谈[5]。在不支持闭包或一等函数的语言中,柯里化也无法直接实现[2]。
参见
参考资料
- [科普中国]-柯里化 [引用日期2026-10-14]
- Currying [引用日期2026-10-14]
- epfl.ch 上的网页 [引用日期2026-10-14]
- epfl.ch 上的网页 [引用日期2026-10-14]
- Js中Currying的应用 [引用日期2026-10-14]
- 柯里化-阿里云开发者社区 [引用日期2026-10-14]
- 浅析 JavaScript 中的 函数 currying 柯里化 [引用日期2026-10-14]
- 前端进阶|详细讲讲函数柯里化 [引用日期2026-10-14]
- 从一道面试题认识函数柯里化 [引用日期2026-10-14]
- tencent.cn 上的网页 [引用日期2026-10-14]
- 【翻译】有帮助的柯里化 [引用日期2026-10-14]