当前位置:首页 > 科技  > 软件

一文看懂:函数式编程为何这么火?

来源: 责编: 时间:2023-12-26 09:30:31 577观看
导读近几年函数式编程变得越来越流行,很多开发语言中都增加了很多函数式编程的能力。比如在JavaScript中使用map函数将数组中的每个元素乘以2:const numbers = [1, 2, 3, 4, 5, 6];const doubled = numbers.map(num => num


M3K28资讯网——每日最新资讯28at.com

近几年函数式编程变得越来越流行,很多开发语言中都增加了很多函数式编程的能力。M3K28资讯网——每日最新资讯28at.com

比如在JavaScript中使用map函数将数组中的每个元素乘以2:M3K28资讯网——每日最新资讯28at.com

const numbers = [1, 2, 3, 4, 5, 6];const doubled = numbers.map(num => num * 2);console.log(doubled); // 输出: [2, 4, 6, 8, 10, 12]

可以看到,这样编写的代码更紧凑、可读性更强。M3K28资讯网——每日最新资讯28at.com

当然函数式编程还有很多好处,本文就带大家来探索下函数式编程的概念和实际应用。M3K28资讯网——每日最新资讯28at.com

1. 什么是函数式编程?

1.1 概念介绍

函数式编程(Functional Programming,简称FP)是一种编程范式,就像你在拼图游戏中只能用特定的块来构建画面,FP要求我们用函数来构建程序的逻辑。这种范式强调将计算过程分解为可复用函数的集合。M3K28资讯网——每日最新资讯28at.com

函数式编程的理论基础是λ演算(lambda),由数学家阿隆佐·邱奇在20世纪30年代引入,这是一套用于研究函数如何定义、如何计算以及如何递归的数学系统。想象一下,λ演算就像是乐高积木的基础板,在这个基础板上,你可以构建任何形式的数据结构和函数,就像你可以用乐高积木构建任何形状的模型一样。M3K28资讯网——每日最新资讯28at.com

图片图片M3K28资讯网——每日最新资讯28at.com

在函数式编程中,函数定义了输入数据与输出数据之间的关系。这可以用我们的初中数学知识来理解:y=f(x) ,它就是函数的最一般定义。M3K28资讯网——每日最新资讯28at.com

函数式编程可以用厨房烹饪来比喻。烹饪中,每道菜的制作都需要一系列步骤,而这些步骤可以被视为一连串的函数。每个函数都是一个烹饪动作,比如切菜、炒菜、煮菜。它们接收原料(输入数据),然后通过一系列处理(函数操作),最终出品一道菜(输出结果)。M3K28资讯网——每日最新资讯28at.com

1.2 函数式编程的精髓

函数式编程的核心理念是描述“做什么”(what to do),而不是“怎么做”(how to do it)。这提供了一个更高的抽象层次,让问题描述得更清晰。M3K28资讯网——每日最新资讯28at.com

举个例子,给你一个装有苹果的篮子,如果我说“挑出所有红苹果”,这就是描述“做什么”,而不是告诉你具体的挑选步骤。M3K28资讯网——每日最新资讯28at.com

再举个代码的例子,计算列表中所有数字的和,使用Haskell编写:M3K28资讯网——每日最新资讯28at.com

sumNumbers = sum [1, 2, 3, 4, 5]

这里,sum是一个函数,它知道如何取一个数字列表并计算它们的和。你不需要告诉它如何去做这件事情(如初始化累加器,循环等等),你只需要告诉它你想要做的事情(计算这个列表的和)。M3K28资讯网——每日最新资讯28at.com

2. 函数式编程的特点2.1 Stateless:无状态函数

函数式编程中的函数不保留任何状态,函数没有副作用,它们只是接受输入并返回输出,而不改变任何外部状态。M3K28资讯网——每日最新资讯28at.com

就像一个好的咖啡机,每次用相同的咖啡豆都能得到一杯品质一致的咖啡。M3K28资讯网——每日最新资讯28at.com

这种无状态的特性使得函数式编程成为一种非常适合进行并行计算和分布式计算的编程范式。M3K28资讯网——每日最新资讯28at.com

2.2 Immutable:不可变数据

在函数式编程中,输入的数据是不可变的。这意味着函数不会改变输入的数据,而是生成新的数据集作为输出。M3K28资讯网——每日最新资讯28at.com

这就像在写字时用铅笔和橡皮擦,函数式编程只允许你用铅笔写在新的纸上,而不是在原来的纸上擦掉重写。M3K28资讯网——每日最新资讯28at.com

3.函数式编程的优势和劣势

3.1 优势

代码简洁

函数式编程大量使用函数,减少了代码的重复,因此程序比较短。M3K28资讯网——每日最新资讯28at.com

并行执行

由于函数不保持状态,它们可以安全地并行执行,就像多个人同时解不同的拼图一样,彼此之间不会产生干扰。M3K28资讯网——每日最新资讯28at.com

无执行顺序问题

函数的执行不依赖于程序的状态,因此不需要担心执行顺序的问题。M3K28资讯网——每日最新资讯28at.com

代码重用性

函数式编程鼓励代码的重用,复制粘贴函数不会引起副作用,就像使用模块化的积木一样,可以在不同的作品中重复使用。M3K28资讯网——每日最新资讯28at.com

延迟执行

函数式编程允许延迟执行,只有在真正需要结果时,才会计算函数的值。M3K28资讯网——每日最新资讯28at.com

确定性

给定相同的输入,函数总是产生相同的输出,这提供了程序的可预测性。M3K28资讯网——每日最新资讯28at.com

3.2 劣势

内存占用大

由于不改变原始数据,可能会导致数据被频繁地复制,这会增加内存的使用,还可能需要更多次的读取和写入操作。M3K28资讯网——每日最新资讯28at.com

学习曲线陡峭

对于习惯了命令式编程的开发者来说,函数式编程的概念可能需要时间来适应。概念如纯函数、不可变性、递归、高阶函数等可能初学者难以理解。M3K28资讯网——每日最新资讯28at.com

4. 函数式编程相关技术4.1 First-class function: 头等函数

在函数式编程中,函数可以作为参数传递,可以作为返回值,也可以赋给变量。这就像在一个游乐园里,所有游乐设施都是“一等公民”,你可以随意搭配使用。M3K28资讯网——每日最新资讯28at.com

4.2 Tail recursion optimization: 尾递归优化

尾递归是一种特殊的递归形式,它允许编译器优化递归调用,避免占用过多的栈空间,使得递归的效率接近循环。M3K28资讯网——每日最新资讯28at.com

4.3 Map & Reduce: 映射与归约

Map和Reduce是处理集合的两个强大工具,它们让代码更加简洁和易读。Map用于转换数据,Reduce用于合并数据。M3K28资讯网——每日最新资讯28at.com

4.4 Pipeline: 管道

管道是一种将多个函数组合起来的方法,数据通过管道流过,依次被这些函数处理。下面是一个管道的例子,在这个例子中,我们首先将number变量值翻倍(double),然后将结果增加1(increment),最后对结果进行平方(square)。M3K28资讯网——每日最新资讯28at.com

from functools import reduce# 定义一系列纯函数def double(x):    return x * 2def increment(x):    return x + 1def square(x):    return x * x# 创建一个函数列表,表示要应用的操作顺序functions = [double, increment, square]# 初始值number = 3# 使用reduce创建一个管道,将函数应用于初始值result = reduce(lambda acc, func: func(acc), functions, number)print(result)  # 输出

4.5 Recursing: 递归

递归是一种强大的编程技术,它让我们可以用简洁的方式描述复杂的问题,正符合函数式编程的精髓。M3K28资讯网——每日最新资讯28at.com

4.6 Currying: 柯里化

柯里化是将接受多个参数的函数转换成一系列使用一个参数的函数的技术。柯里化可以使代码更加模块化,每个函数的功能更加单一,这有助于提高代码的可读性和可维护性。同时,柯里化也可以使代码更加灵活,因为我们可以通过组合不同的函数来实现不同的功能。举个例子:M3K28资讯网——每日最新资讯28at.com

def add(a, b):    return a + bdef curry_add(a):    def add_b(b):        return add(a, b)    return add_b# 使用柯里化的add函数add_5 = curry_add(5)  # 创建一个新的函数,这个函数会将其参数加5print(add_5(10))  # 输出: 15

当我们调用curry_add(5)时,我们得到了一个新的函数add_5,它固定了第一个参数为5,并等待第二个参数。当我们随后调用add_5(10)时,它实际上调用的是add(5, 10)。M3K28资讯网——每日最新资讯28at.com

4.7 Higher-order function: 高阶函数

高阶函数可以接受其他函数作为参数或者将函数作为返回值。这类似于你有一个能装其他小盒子的大盒子,这个大盒子可以用来组织和管理那些小盒子。M3K28资讯网——每日最新资讯28at.com

举个Python中的例子,reduce就是一个高阶函数,在这里它的第一个参数是匿名函数。M3K28资讯网——每日最新资讯28at.com

from functools import reduce    def sum_numbers(numbers):      return reduce(lambda x, y: x + y, numbers, 0)

5. 函数式编程语言

很多语言都提供了函数式编程的支持,不过支持的程度不太一样,这里做个简单的总结。M3K28资讯网——每日最新资讯28at.com

Haskell: 完全纯函数式编程语言M3K28资讯网——每日最新资讯28at.com

Haskell是一个标准的纯函数式编程语言,所有的操作都是通过函数来完成的,就像在一个世界里,所有的建筑都是用同一种类型的积木搭建的。M3K28资讯网——每日最新资讯28at.com

F#, Ocaml, Clojure, Scala: 容易写纯函数的语言M3K28资讯网——每日最新资讯28at.com

这些语言设计时考虑到了函数式编程的特性,使得编写纯函数变得容易。M3K28资讯网——每日最新资讯28at.com

C#, Java, JavaScript: 需要花点精力写纯函数的语言M3K28资讯网——每日最新资讯28at.com

虽然这些语言不是纯函数式编程语言,但它们提供了支持函数式编程的特性,只是需要程序员更加注意避免副作用。M3K28资讯网——每日最新资讯28at.com

大部分语言都支持的函数式编程三套件:Map、Reduce、FilterM3K28资讯网——每日最新资讯28at.com

这三个函数是函数式编程中处理数据集合的基本工具,就像在厨房里的刀、叉、勺是处理食物的基础一样。M3K28资讯网——每日最新资讯28at.com

6. 装饰器模式

这里之所以提到装饰器模式,是因为它和函数式编程有很多共同点。函数式编程和装饰器模式都关注于函数的灵活性、可复用性和不修改现有代码的原则。M3K28资讯网——每日最新资讯28at.com

装饰器模式可以向现有功能添加新功能,而不改变其结构。这就像给一个手机装上手机壳,增加了新的功能(比如防摔),但手机本身并没有改变。M3K28资讯网——每日最新资讯28at.com

图片图片M3K28资讯网——每日最新资讯28at.com

装饰器的本质就是函数,它也遵循函数式编程的一些原则。下边我们提供两个例子。M3K28资讯网——每日最新资讯28at.com

6.1 Python中的装饰器

在Python中,装饰器模式通常使用装饰器函数来实现。装饰器函数是一个接受函数作为参数,并返回一个新的函数的函数。通过装饰器函数,我们可以动态地给一个函数添加一些新的功能,比如日志记录、性能测试、事务处理等。M3K28资讯网——每日最新资讯28at.com

下面是一个简单的示例,演示了如何使用装饰器函数来给一个函数添加日志记录功能:M3K28资讯网——每日最新资讯28at.com

def log(func):      def wrapper(*args, **kwargs):          print("Calling function:", func.__name__)          result = func(*args, **kwargs)          print("Function returned:", result)          return result      return wrapper    @log  def add(x, y):      return x + y

当我们使用@log注解add时,我们实际上是将add传递给了log,并且使用log返回的wrapper函数来替代原始的add。M3K28资讯网——每日最新资讯28at.com

6.2 Golang的装饰器

在Go语言中,装饰器模式没有语法糖像Python的装饰器那样直观。在Go中,你需要手动将一个函数传递给另一个函数,从而实现装饰。下面还是记录日志的例子:M3K28资讯网——每日最新资讯28at.com

package main  import "fmt"  // 原始函数  func add(x, y int) int {      return x + y  }  // 装饰器函数  func logDecorator(f func(int, int) int) func(int, int) int {      return func(x, y int) int {          fmt.Printf("Calling function: add/n")          result := f(x, y)          fmt.Printf("Function returned: %d/n", result)          return result      }  }  func main() {      // 使用装饰器函数包装原始函数      decoratedAdd := logDecorator(add)      // 调用装饰后的函数      fmt.Println(decoratedAdd(2, 3))  }

7. 函数式编程在实际中的应用

大数据处理:在大数据领域,函数式编程的概念,特别是Map和Reduce,被广泛应用于数据的处理。想象一下,你有一座由许多小石头组成的山,Map就是用来挑选出你需要的石头,而Reduce则帮你把这些石头粘合成一座小山丘。M3K28资讯网——每日最新资讯28at.com

响应式编程:响应式编程(Reactive Programming)是一种与函数式编程有着密切关系的编程范式,它侧重于数据流和变化的传播。这就像是一个复杂的多米诺骨牌装置,当你触动一个骨牌,整个装置按照既定的路径和顺序倒下。M3K28资讯网——每日最新资讯28at.com

Web开发:在Web开发中,函数式编程也有其用武之地。例如,React库利用了函数式编程的概念来管理用户界面的状态,使得状态的变化可预测和可管理。M3K28资讯网——每日最新资讯28at.com

并发编程:函数式编程的无状态和不可变性使得它在并发编程中非常有用。它可以帮助避免并发时常见的问题,如竞态条件和死锁。M3K28资讯网——每日最新资讯28at.com

8. 如何学习函数式编程?

  1. 从基础概念开始:理解函数式编程的关键是从其基本概念开始,比如纯函数、不可变性和函数组合。就像学习任何新技能一样,掌握基础是成功的关键。
  2. 学习和实践:学习函数式编程不仅仅是理论上的,更重要的是通过实践来深化理解。尝试用函数式编程解决实际问题,就像是通过游戏来学习游泳,理论知识和实际动作的结合才能让你游得更好。
  3. 使用函数式编程语言:尝试使用像Haskell这样的纯函数式编程语言,或者在支持函数式编程的语言中使用函数式特性,比如JavaScript中的高阶函数和数组方法。
  4. 参与社区和项目:加入函数式编程的社区,参与开源项目,这可以帮助你更快地学习和应用函数式编程的概念。

结语

函数式编程是一个非常强大且具有挑战性的编程范式,它提供了一种不同的思考和解决问题的方式。虽然它可能看起来有点像是数学或者哲学,但一旦你掌握了它,就会发现它能帮你写出更清晰、更可维护、更可靠的代码。M3K28资讯网——每日最新资讯28at.com


M3K28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-54187-0.html一文看懂:函数式编程为何这么火?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 20行经典C代码,很多人看不明白,你来试一下?

下一篇: 数据齐舞:深入浅出分布式事务的八奇技

标签:
  • 热门焦点
  • Find N3入网:最高支持16+1TB

    OPPO将于近期登场的Find N3折叠屏目前已经正式入网,型号为PHN110。本次Find N3在外观方面相比前两代有很大的变化,不再是小号的横向折叠屏,而是跟别的厂商一样采用了较为常见的
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 共享单车的故事讲到哪了?

    来源丨海克财经与共享充电宝相差不多,共享单车已很久没有被国内热点新闻关照到了。除了一再涨价和用户直呼用不起了。近日多家媒体再发报道称,成都、天津、郑州等地多个共享单
  • 拼多多APP上线本地生活入口,群雄逐鹿万亿市场

    Tech星球(微信ID:tech618)文 | 陈桥辉 Tech星球独家获悉,拼多多在其APP内上线了“本地生活”入口,位置较深,位于首页的“充值中心”内,目前主要售卖美食相关的
  • 华为Mate 60保护壳曝光:硕大后置相机模组 凸起程度有惊喜

    这段时间以来,关于华为新旗舰的爆料日渐密集。据此前多方爆料,今年华为将开始恢复一年双旗舰战略,除上半年推出的P60系列外,往年下半年的Mate系列也将
  • 三星获批量产iPhone 15全系屏幕:苹果史上最惊艳直屏

    按照惯例,苹果将继续在今年9月举办一年一度的秋季新品发布会,有传言称发布会将于9月12日举行,届时全新的iPhone 15系列将正式与大家见面,不出意外的话
  • 到手价3099元起!iQOO Neo8 Pro今日首销:安卓性能最强旗舰

    5月23日,iQOO如期举行了新品发布会,全新的iQOO Neo8系列也正式与大家见面,包含iQOO Neo8和iQOO Neo8 Pro两个版本,其中标准版搭载高通骁龙8+,而Pro版更
  • iQOO Neo8系列或定档5月23日:首发天玑9200+ 安卓跑分王者

    去年10月,iQOO推出了iQOO Neo7系列机型,不仅搭载了天玑9000+,而且是同价位唯一一款天玑9000+直屏旗舰,一经上市便受到了用户的广泛关注。在时隔半年后,
Top