与部分应用(Partial Application)的区别与实现)
教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载柯里化Currying与部分应用Partial Application都是将函数转换为「参数个数更少」的另一函数的两种经典函数式编程手法。本文以 jstips 第 28 期 柯里化和部分應用程式 为核心骨架结合仓库中的中英文对应版本讲透二者的数学定义、JavaScript 实现、核心区别与实用场景读完即可写出自己的curry与partApply工具函数并正确判断何时该用哪一种。一、为什么要区分柯里化与部分应用在函数式编程中我们经常希望把一个「一次接收多个参数」的函数改造成「能分步接收参数」的形式从而复用中间结果、组合小函数或延迟执行。jstips第 28 期用最简洁的方式点明了二者的定位Currying and partial application are two ways of transforming a function into another function with a generally smaller arity.即柯里化和部分应用都是把一个函数转换成另一个「通常参数个数arity更小」的函数的方法。但二者转换的规则完全不同——柯里化改变的是函数的调用形态而部分应用改变的是函数的参数数量。下面分别展开。二、柯里化Currying把二元函数拆成一串一元函数2.1 数学定义柯里化是将一个函数f: X * Y - R转换成f: X - (Y - R)与「用两个参数调用f」不同我们先用第一个参数调用f得到的结果是一个函数再用第二个参数调用这个函数最终得到结果。因此未柯里化的f是这样调用的f(3, 5)而柯里化后的f是这样调用的f(3)(5)2.2 代码对比未柯里化 vs 柯里化未柯里化的加法函数function add(x, y) { return x y; } add(3, 5); // returns 8柯里化后的加法函数function addC(x) { return function (y) { return x y; } } addC(3)(5); // returns 8注意两者的关键差异addC(3)并不立即求和而是返回一个「记住了x 3的闭包函数」该闭包等待第二个参数y传入后才计算x y。这正是闭包closure在函数式编程中的典型应用——内层函数通过作用域链捕获外层参数x。2.3 柯里化的规则与通用实现柯里化将一个二元函数转变为一个一元函数这个一元函数又返回另一个一元函数curry: (X × Y → R) → (X → (Y → R))通用的柯里化实现来自 第 28 期文档function curry(f) { return function(x) { return function(y) { return f(x, y); } } }调用方式curry(add)(3)(5)返回8。curry接受一个二元函数f先固定住第一个参数x返回一个等待y的新函数最终在两层闭包都就位后才调用原始函数f(x, y)。2.4 向多元函数的自然延伸仓库中的另一期姊妹篇 What is a currying function?tip #75进一步说明柯里化函数将一个「接收多个参数的函数」转变为「一次只接收一个参数的函数序列」即 n 元函数变成一元函数串最后一个函数汇总所有参数并返回结果。以三元乘法为例// Normal definition function multiply(a, b, c) { return a * b * c; }; console.log(multiply(1, 2, 3)); // Output: 6 // Simple curry function definition function multiply(a) { return (b) { return (c) { return a * b * c; }; }; }; console.log(multiply(1)(2)(3)); // Output: 6可见柯里化的本质是「逐个接收参数每接收一个参数返回一个新函数直到所有参数集齐才真正执行」。三、部分应用Partial Application先固定部分参数生成参数更少的函数3.1 数学定义部分应用将一个函数f: X * Y - R的第一个参数固定产生一个新的函数f: Y - Rf与f做的事相同但只需要填写第二个参数这就是为什么f比f少一个参数arity 少 1。3.2 代码示例绑定第一个参数例如把函数add的第一个参数固定为 5产生新函数plus5function plus5(y) { return 5 y; } plus5(3); // returns 83.3 部分应用的规则与通用实现部分应用使用一个二元函数和一个值产生一个一元函数partApply: ((X × Y → R) × X) → (Y → R)通用的部分应用实现同样来自 第 28 期文档function partApply(f, x) { return function(y) { return f(x, y); } }调用方式partApply(add, 5)(3)返回8。与柯里化不同partApply在一次调用中同时接收「函数」和「固定值」两个参数立刻产出「参数更少的新函数」。四、柯里化 vs 部分应用一张表看清区别维度柯里化Currying部分应用Partial Application转换规则(X × Y → R) → (X → (Y → R))((X × Y → R) × X) → (Y → R)输入一个函数一个函数 一个固定值产物一元函数 →再返回一元函数直接得到一个一元函数每次调用接收参数数1 个可以接收多个函数 已固定值调用形态f(3)(5)partApply(f, 3)(5)返回的新函数仍可能继续接收参数、继续柯里化参数个数已经确定减少等待剩余参数核心目的把多参调用改造成可分步、可延迟的链式调用预先「配置」部分参数产出专用函数一句话总结二者的差异这也是 第 28 期 想传递的核心结论柯里化改变调用方式——「一次只喂一个参数」每次调用都返回一个新函数部分应用改变参数数量——「一次性固定若干个参数」产出一个参数更少的函数之后只补剩余参数。五、实战柯里化与部分应用在真实代码中的用法5.1 柯里化用于延迟执行与参数复用柯里化最常见的价值是「分步传参」例如按需生成带固定上下文的函数function log(level) { return function (message) { console.log([${level}] ${message}); }; } const info log(INFO); const error log(ERROR); info(user logged in); // [INFO] user logged in error(disk full); // [ERROR] disk full5.2 部分应用用于「配置化」函数部分应用适合「先配置、后使用」的场景例如预置税率、汇率或折扣function partApply(f, x) { return function(y) { return f(x, y); } } function calculatePrice(price, taxRate) { return price price * taxRate; } // 固定税率 0.08生成专用函数 const withTax partApply(calculatePrice, 100); withTax(0.08); // 1085.3 与原生bind的对应关系JavaScript 原生的Function.prototype.bind本质上就是一种部分应用同时还能绑定this。仓库中的 Binding objects to functionstip #61展示了其语法fun.bind(thisArg[, arg1[, arg2[, ...]]])其中arg1, arg2, ...就是「预置参数」调用绑定后的函数时只需补足剩余参数——这正是部分应用的思想。因此实际开发中你可以直接用add.bind(null, 5)实现plus5而无需手写partApply。六、如何继续在本仓库中深入学习本主题的多语言对照繁体中文 2016-01-28-curry-vs-partial-application.md、简体中文 2016-01-28-curry-vs-partial-application.md、英文 2016-01-28-curry-vs-partial-application.md便于对照阅读柯里化的多元扩展What is a currying function?tip #75部分应用的 Native 实现bind详解见 Binding objects to functionstip #61仓库 README.md 的 Tips 列表中第 28 期条目即本主题Currying vs partial application可在官方博客中按期查阅。结语柯里化与部分应用是函数式编程中极易混淆的两个概念柯里化重构的是「如何调用」——一次只传一个参数形成函数串部分应用重构的是「函数的形状」——预先固定参数产出更专用的函数。理解二者的数学规则curry与partApply的类型签名后你就掌握了判断标准若想让调用变成f(3)(5)的分步形态用柯里化若想快速产出一个「参数更少」的专用函数用部分应用或直接使用bind。这两种手法在事件处理、配置复用、函数组合等场景中都有着广泛的应用价值。赞分享教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载相关推荐jstips 第 28 期解读柯里化Currying与部分应用Partial Application的深入对比jstips 第 28 期解读柯里化Currying与部分应用Partial Application的深入对比 导读 本文基于 jstips 仓库中编教程深入理解 jstips 第 28 期柯里化Currying与偏函数应用Partial Application的区别与实践深入理解 jstips 第 28 期柯里化Currying与偏函数应用Partial Application的区别与实践 柯里化与偏函数应用是函数式编教程JS Tips柯里化Currying与部分应用Partial Application深入解析JS Tips柯里化Currying与部分应用Partial Application深入解析 本文内容基于 jstips 仓库第 28 期 JavaS教程上一篇解锁电视盒子潜能ZXV10 B860AV3.2-M 变身Linux服务器完全刷机教程下一篇3个步骤解决HEIC缩略图不显示问题Windows系统图像预览解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考