柯里化

简介: 柯里化

本文旨在介绍函数式编程中柯里化的概念,以及在JavaScript中应该何时使用它。

本文将首先解释什么是柯里化,然后展示它在函数式编程背景下的用处。


什么是柯里化


柯里化是指函数永远只接受一个参数,如果需要处理多个参数,则返回另一个函数来接收单一的参数。相比之下,常规非柯里化函数可以接受多个参数。

以下是一个常规、非柯里化函数的例子:


const add = (x, y) => x + y
console.log(
  add(2, 3) // 2 + 3
) // prints 5


这是一个简单的函数,它接受两个参数并返回它们的和。

相同函数的柯里化版本如下所示:


const addCurried = x => y => x + y
console.log(
  addCurried(2)(3) // 2 + 3
) // prints 5


该函数不是接收两个参数,而是接收一个参数,然后返回另一个接收一个参数并返回两参数之和的函数。

通过这种方式,我们可以传递任意数量的参数:


const addMore = a => b => c => d => e => a + b + c + d + e
console.log(
  addMore(1)(2)(3)(4)(5) // 1 + 2 + 3 + 4 + 5
) // prints 15


由于柯里化函数的工作方式,我们可以进行称为部分应用的操作。部分应用是指我们向函数提供少于其可以接受的参数数量的参数:


const addCurried = x => y => x + y
console.log(
  addCurried(2) // y => 2 + y
) // [Function (anonymous)]


如果我们仅向 addCurried 函数传递一个参数,则结果是一个,接收一个参数的函数。换句话说,数字 2 传递给了 x 参数,因此我们得到的值是 y => 2 + y。如果需要的话,我们可以将这个部分应用的函数存储到一个变量中,以便在以后复用


const addCurried = x => y => x + y
const add2 = addCurried(2)
// This is the same as:
// const add2 = y => 2 + y
console.log(
  add2(3) // 2 + 3
) // prints 5
console.log(
  add2(10) // 2 + 10
) // prints 12


现在我们有了一个名为 add2 的函数,它可以接收一个参数。不管我们给它传入什么参数,它都会+2 。


什么时候使用柯里化函数呢?


函数柯里化在我们的普通的函数时是没有什么优势的,他的真正优势在于组合使用,只有在组合使用时才它能真正发挥了作用。

在 JavaScript 中,组合两个函数的方式如下所示:


const compose = (f, g) => x => f(g(x))
const addCurried = x => y => x + y
console.log(
  compose(addCurried(2), addCurried(3))(10) // 10 + 3 + 2 = 15
) // prints 15


让我们来理解上面的操作,

  • addCurried(2)=2+y,addCurried(3)=3+y
  • compose(addCurried(2), addCurried(3))=2+(3+y)
  • 又因为(f, g) => x => f(g(x))返回的是一个函数,这个函数接收一个参数值x
  • 所以compose(addCurried(2), addCurried(3))=2+(3+y) =x =>2+(3+x)
  • 又因为我又传入了一个值10
  • 所以最终结果就是2+(3+10)=15
目录
相关文章
如何在cmd中打开指定文件夹路径
如何在cmd中打开指定文件夹路径
2116 0
|
存储 数据采集 大数据
Flink实时湖仓,为汽车行业数字化加速!
本文由阿里云计算平台产品专家李鲁兵(云觉)分享,聚焦汽车行业大数据应用。内容涵盖市场趋势、典型大数据架构、产品市场地位及能力解读,以及典型客户案例。文章详细介绍了新能源汽车市场的快速增长、大数据架构分析、实时湖仓方案的优势,以及Flink和Paimon在车联网中的应用案例。
764 8
Flink实时湖仓,为汽车行业数字化加速!
|
数据可视化 算法 Java
了解go语言运行时工具的作用
【5月更文挑战第16天】本文简介`runtime`库提供系统调用包装、执行跟踪、内存分配统计、运行时指标和剖析支持。`internal/syscall`封装系统调用,保证uintptr参数有效。`trace`用于执行跟踪,捕获各种事件,如goroutine活动、系统调用和GC事件。`ReadMemStats`提供内存分配器统计。`metrics`接口访问运行时定义的度量,包括CPU使用、GC和内存信息。`coverage`支持代码覆盖率分析,`cgo`处理C语言交互,`pprof`提供性能剖析工具集成。这些功能帮助优化和理解Go程序的运行行为。
217 6
|
存储 Java
JavaSE基础精选-IO流
JavaSE基础精选-IO流
138 0
|
存储 缓存
|
Linux Docker 容器
Docker-01:Docker安装及更换源
Docker容器镜像仓库地址更改,解决Docker镜像仓库下载慢的问题,提高镜像下载速度
3557 0
Docker-01:Docker安装及更换源
|
SQL 存储 关系型数据库
索引的创建与设计原则(1)
索引的创建与设计原则(1)
索引的创建与设计原则(1)
|
存储 缓存 监控
如果你是 JDK 设计者,如何设计线程池?我跟面试官大战了三十个回合(下)
如果你是 JDK 设计者,如何设计线程池?我跟面试官大战了三十个回合(下)
如果你是 JDK 设计者,如何设计线程池?我跟面试官大战了三十个回合(下)
|
Oracle 关系型数据库 Windows