函数式编程:初识函数式编程

21 篇文章 3 订阅
3 篇文章 0 订阅

我们在经历了面向对象编程、面向过程编程之后,函数式编程又进入了我们的视线。其实,函数式编程并不是一个什么新鲜的东西。它早在上世纪50年代,随着 Lisp 语言的创建,就已经诞生。而近些年,随着react hooks的发布,函数式编程以其优雅,简单的特点再次出现在大众的视线中。函数式编程这种古老的编程范式并没有随着岁月而褪去其光彩,反而愈加生机勃勃。

什么是函数式编程?

关于函数式编程,维基百科是这样说的:函数式编程是一种编程范畴。他将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基本的是λ演算。而且λ演算的函数可以接受函数作为输入和输出。比起命令式编程,函数式编程更加强调程序执行的结果而非执行的过程。倡导利用若干个简单的执行单元,让计算结果不断的渐进。逐渐推到复杂的运算。而不是设计一个复杂的执行过程。

这段话看起还是比较难以理解,那么我来翻译一下:其实,就是在说,函数式编程就是要把逻辑封装到函数中,只要设计好入参是什么,函数执行的结果是什么,而不必关心函数中的逻辑是怎么执行的。当然在函数中的执行逻辑还可以分为若干个单元,用于解耦逻辑。就是这么简单。

为什么要函数式编程

其实,我们对于函数从来都不陌生,函数就是描述一个集合和另外一个集合之间的转换关系。输入通过函数都会返回有且只有一个输出值。所以,函数实际上是一个关系,或者说是一种映射,而这种映射关系是可以组合的,一旦我们知道一个函数的输出类型可以匹配另一个函数的输入,那他们就可以进行组合。

举个例子来说,函数式编程的思想就像是某一条生产线一样。当我们从最开始将原料(入参)放入机器(函数)后,我们并不需要关注机器做了些什么,或者是怎么做的,我们只是需要关系,最后输出的产品(函数返回值)合不合格就OK。也许在机器成产的过程,会需要多台机器,中间做了n步转化,那么这就是我们所说的函数的组合,这样的一条生产线是不是效率就更高,看起来也更简介呢?

函数式编程的特点

  • 函数是一等公民

这是函数式编程得以实现的前提,因为我们基本的操作都是在操作函数。这个特性意味着函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。

  • 声明式编程

函数式编程大多时候都是在声明我需要做什么,而非怎么去做。这种编程风格称为声明式编程 。这样有个好处是代码的可读性特别高,因为声明式代码大多都是接近自然语言的,同时,它解放了大量的人力,因为它不关心具体的实现,因此它可以把优化能力交给具体的实现,这也方便我们进行分工协作。

  • 惰性执行

惰性执行还是比较好理解的。就是说函数只有在被调用的时候,才会产生一些中间变量,否则是不会去产生哪些无关紧要的没有意义的东西。

  • 无状态数据不可变

数据不可变: 它要求你所有的数据都是不可变的,这意味着如果你想修改一个对象,那你应该创建一个新的对象用来修改,而不是修改已有的对象。

无状态: 主要是强调对于一个函数,不管你何时运行,它都应该像第一次运行一样,给定相同的输入,给出相同的输出,完全不依赖外部状态的变化。

  • 没有副作用

在完成函数主要功能之外完成的其他副要功能。在我们函数中最主要的功能当然是根据输入返回结果,而在函数中我们最常见的副作用就是随意操纵外部变量。由于 JS 中对象传递的是引用地址,哪怕我们用 const 关键词声明对象,它依旧是可以变的。而正是这个“漏洞”让我们有机会随意修改对象。

 

保证函数没有副作用,一来能保证数据的不可变性,二来能避免很多因为共享状态带来的问题。当你一个人维护代码时候可能还不明显,但随着项目的迭代,项目参与人数增加,大家对同一变量的依赖和引用越来越多,这种问题会越来越严重。最终可能连维护者自己都不清楚变量到底是在哪里被改变而产生 Bug。

  • 纯函数

纯函数是在没有副作用的基础上更进一步的要求,在redux中体现的更加直观,单向数据流、单一store、纯函数。主要有俩点注意:

(1)不依赖外部状态(无状态): 函数的的运行结果不依赖全局变量,this 指针,IO 操作等。

(2)没有副作用(数据不变): 不修改全局变量,不修改入参。

所以纯函数才是真正意义上的 “函数”, 它意味着相同的输入,永远会得到相同的输出。那么为什么要纯函数呢,纯函数的意义是什么呢?

1、便于测试和优化:这个意义在实际项目开发中意义非常大,由于纯函数对于相同的输入永远会返回相同的结果,因此我们可以轻松断言函数的执行结果,同时也可以保证函数的优化不会影响其他代码的执行。这十分符合测试驱动开发 TDD(Test-Driven Development ) 的思想,这样产生的代码往往健壮性更强。

2、可缓存性:因为相同的输入总是可以返回相同的输出,因此,我们可以提前缓存函数的执行结果,有很多库有所谓的 memoize 函数。

3、自文档化:由于纯函数没有副作用,所以其依赖很明确,因此更易于观察和理解。

4、更少的 Bug:使用纯函数意味着你的函数中不存在指向不明的 this,不存在对全局变量的引用,不存在对参数的修改,这些共享状态往往是绝大多数 bug 的源头。

函数柯理化

函数柯理化就是我们生产线上的加工站,我们需要函数柯理化,我们需要将一个多元参数转变成一个单元参数的函数。

(1)部分函数应用 vs 柯里化

部分函数应用强调的是固定一定的参数,返回一个更小元的函数

柯里化强调的是生成单元函数部分函数应用的强调的固定任意元参数,而我们平时生活中常用的其实是部分函数应用,这样的好处是可以固定参数,降低函数通用性,提高函数的适合用性。

// 柯里化
f(a,b,c) → f(a)(b)(c)
// 部分函数调用
f(a,b,c) → f(a)(b,c) / f(a,b)(c)

我们可以用高级柯里化去实现部分函数应用,但是柯里化不等于部分函数应用。们在实践中使用柯里化都是为了把某个函数变得单值化,这样可以增加函数的多样性,使得其适用性更强。

组合函数

组合函数就是我们所谓的生产线。将多个函数,组成一个比较复杂的函数。函数组合的好处显而易见,它让代码变得简单而富有可读性,同时通过不同的组合方式,我们可以轻易组合出其他常用函数,让我们的代码更具表现力。

函数式编程初探,大概就是这么多内容,真的真的很好,赶紧学啊。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值