函数式编程了解一下

发布于 2022-06-01 13:19:21 字数 2701 浏览 1108 评论 0

函数式编程是一种编程范式,我们常见的编程范式有命令式编程(Imperative programming),函数式编程逻辑式编程常见的面向对象编程是也是一种命令式编程

命令式编程是面向计算机硬件的抽象,有变量(对应着存储单元),赋值语句(获取,存储指令),表达式(内存引用和算术运算)和控制语句(跳转指令),一句话,命令式程序就是一个冯诺依曼机的指令序列

而函数式编程是面向数学的抽象,将计算描述为一种表达式求值,一句话,函数式程序就是一个表达式

为什么函数式编程要求函数必须是纯的,不能有副作用?因为它是一种数学运算,原始目的就是求值,不做其他事情,否则就无法满足函数运算法则了。

本质

函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。

在函数式语言中,函数作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合。

纯函数式编程语言中的变量也不是命令式编程语言中的变量,即存储状态的单元,而是代数中的变量,即一个值的名称。变量的值是不可变的(immutable),也就是说不允许像命令式编程语言中那样多次给一个变量赋值。比如说在命令式编程语言我们写“x = x + 1”,这依赖可变状态的事实,拿给程序员看说是对的,但拿给数学家看,却被认为这个等式为假。

函数式语言的如条件语句,循环语句也不是命令式编程语言中的控制语句,而是函数的语法糖,比如在Scala语言中,if else不是语句而是三元运算符,是有返回值的。

严格意义上的函数式编程意味着不使用可变的变量,赋值,循环和其他命令式控制结构进行编程。

从理论上说,函数式语言也不是通过冯诺伊曼体系结构的机器上运行的,而是通过λ演算来运行的,就是通过变量替换的方式进行,变量替换为其值或表达式,函数也替换为其表达式,并根据运算符进行计算。λ演算是图灵完全(Turing completeness)的,但是大多数情况,函数式程序还是被编译成(冯诺依曼机的)机器语言的指令执行的

特点

不可变性

不可变数据是指该变量在创建是会固定一个值之后不能再修改;
对不可变数据(对象)操作后返回一个新的对象;

引用透明(Referential transparency)

函数的返回值只依赖于其输入值,这种特性就称为引用透明性

没有副作用

只要是跟函数外部环境发生的交互就都是副作用。从“副作用”这个词语来看,它更多的情况在于“改变系统状态”。

好处

函数式的最主要的好处主要是不可变性带来的。

没有可变的状态,函数就是引用透明(Referential transparency)的和没有副作用(No Side Effect)。

并且,函数即不依赖外部的状态也不修改外部的状态,函数调用的结果不依赖调用的时间和位置,这样写的代码容易进行推理,不容易出错。这使得单元测试和调试都更容易。

不变性带来的另一个好处是:由于(多个线程之间)不共享状态,不会造成资源争用(Race condition),也就不需要用来保护可变状态,也就不会出现死锁,这样可以更好地并发起来,尤其是在对称多处理器(SMP)架构下能够更好地利用多个处理器(核)提供的并行处理能力。

由于函数是引用透明的,以及函数式编程不像命令式编程那样关注执行步骤,这个系统提供了优化函数式程序的空间,包括惰性求值和并性处理。

还有一个好处是,由于函数式语言是面向数学的抽象,更接近人的语言,而不是机器语言,代码会比较简洁,也更容易被理解。

限制

不能使用循环操作,严重依赖递归

同样由于变量不可变,纯函数编程语言无法实现循环,这是因为For循环使用可变的状态作为计数器,而While循环或DoWhile循环需要可变的状态作为跳出循环的条件。因此在函数式语言里就只能使用递归来解决迭代问题,这使得函数式编程严重依赖递归。

尾递归调用

当然,这样的递归调用有更高的开销和局限(调用栈深度),那么尽量把递归写成尾递归的方式,编译器会自动优化为循环,这里就不展开介绍了。 一般来说,递归这种方式于循环相比被认为是更符合人的思维的,即告诉机器做什么,而不是告诉机器怎么做。递归还是有很强大的表现力的。

用途

  • 高阶函数(Higher-order function)
  • 偏应用函数(Partially Applied Functions)
  • 柯里化(Currying)
  • 闭包(Closure)

高阶函数提供了一种函数级别上的依赖注入(或反转控制)机制。高阶函数的逻辑依赖于注入进来的函数的逻辑。

Reference

什么是函数式编程思维?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

文章
评论
84963 人气
更多

推荐作者

微信用户

文章 0 评论 0

小情绪

文章 0 评论 0

ゞ记忆︶ㄣ

文章 0 评论 0

笨死的猪

文章 0 评论 0

彭明超

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文