最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 聊一聊函数式编程中的副作用概念

    正文概述 掘金(夜还不够黑丶)   2020-12-19   407

    前言

    今天聊一聊函数式编程中的隔离思想,它所想隔离的就是“副作用”

    我们先从其他角度来聊一聊副作用这个概念。

    生活中的副作用

    如果我听到副作用这个词后,第一反应是吃药? 。

    老话说是药三分毒,其中三分毒则为副作用。就比如你?感冒了,吃了一些西方某些国家研制的专利药品,然后感冒好了,但是感冒好了之后发现自己秃顶?‍? 了。

    那么可以说秃顶就是这个感冒药的副作用。

    我们来捋一下这个逻辑

    • 感冒好没好? 答: 好了
    • 这药算不算感冒药 ? 答: 算感冒药
    • 不吃这个药的话感冒就不会好,吃不吃 ? 答: 吃
    • 副作用可不可以忍受 ? 答: 至少本来就没头发可以忍

    上面的副作用有些夸大其词了,但是药物一般来说都会有一些副作用。

    那么话说回来,程序中呢?

    程序的副作用是什么

    在I/O模型中,我们希望在在I到O之间只有计算,如果中间包含且不仅包含触发了其他I/O、与此次I -> O计算并不相关的任何事情,都称为副作用。

    聊一聊函数式编程中的副作用概念

    为什么称之为副作用这样的词语呢,“副作用”这个单词给人第一感觉是糟糕的,从而想让你警惕起来。如果在I/O之间发生了一些我们不知道的副作用,那么我们将无法控制住这个过程,测试过程也会变得非常复杂

    可以想像,如果在I/O之间如果要访问数据库,则必须确保数据库正在运行。如果要写入文件,则必须确保该文件存在并已打开。所以会导致执行过程和测试过程变得很复杂,并不是单一的点对点。

    写到这里让我不禁想起了PromiseA+规范的测试用例,官方提供了872种测试用例,你所实现的Promise必须全部通过872种测试用例才符合官方规范。

    无副作用的优势

    如果一个I/O模型之间没有副作用的话会有什么样的优势呢?我们参照最开始生活角度的那个例子。

    如果感冒药换成某东方国家生产的无副作用的药品,在我们感冒的时候,吃感冒药,感冒好了。过程中无任何副作用的产生,不会秃顶。

    那么我们就可以放心的在感冒的情况下吃这种药品,而不用考虑其他情况。这就是一个纯的I/O模型。

    在编程中,我们声明了一个函数double,如下

    聊一聊函数式编程中的副作用概念

    在每次输入x = 3的情况下,double返回恒等与6。它不依赖于我们传递它的参数之外的任何东西

    可以想像,在我们调用double的时候,地球上发生着各种各样的事情,如果在调用的瞬间,天上出现了奥特曼,double依然输出6。在固定输入的情况下它是永恒的。

    当你写下这个函数之后,你的余生都可以放心使用它,无论上下文如何,它将永久有效。

    永恒的东西变化的频率较低,测试起来更加容易,调试起来更加容易。这就是为什么现在很多编程语言都倾向于无副作用。

    函数式编程中的副作用概念

    函数式编程是基于没有副作用的这样一个简单的前提。在这种范例中,副作用是被排斥的。

    如果函数有副作用,我们将其称为过程,或者命令式。因此函数没有副作用。我们认为,如果函数修改了可变数据结构或变量,使用I/O,引发异常或中止错误,则将产生副作用。所有这些东西都被认为是副作用。

    副作用之所以不好,是因为(如果有)副作用,取决于系统状态,功能可能是不可预测的。当一个函数没有副作用时,我们可以随时执行它,在给定相同的输入的情况下,它将始终返回相同的结果

    但是要声明一点,函数式编程并不是不需要副作用,只是在需要时限制它们。

    需要有副作用,因为没有它们,我们的程序将只能进行计算。

    我们经常必须写数据库,与外部系统集成或写文件。与外界通过接口的形式交互才能将我们的计算展示出去。所以很多倾向无副作用的语言的中心细想是把“作用”与“副作用”分离开来处理。

    下面我们通过一些特性来看一下。

    参照透明

    对于同一输入总是返回相同结果的函数称为纯函数。因此,纯函数是没有可观察到的副作用的函数,如果函数有任何副作用,即使我们使用相同的参数调用它,也可能返回不同的结果。所以我们可以将纯函数替换为其计算值,例如:

    聊一聊函数式编程中的副作用概念

    如果我们输入x = 2, y = 2,那么我们可以得到 4 = sum(2, 2)。

    那么sum为纯函数吗?很显然是的,如果我们恒定传入x = 2, y = 2。那么sum将恒定输出4.

    那么意味着 f(2, 2) 可以替换为4,比如 Math.floor(sum(2, 2)) 替换之后 Math.floor(4),是一致的。

    它就像一个很大的查询表。我们可以这样做是因为它没有任何副作用。用其计算值替换表达式的能力称为参照透明性。

    引用透明很重要,因为它允许我们用值替换表达式。此属性使我们能够使用替换模型来思考和推理程序评估。因此,可以说可以用值替换的表达式是确定性的,因为它们始终为给定的输入返回相同的值。

    局部副作用

    在讲局部副作用之前,我们先来举一个非局部副作用的典型例子?。

    聊一聊函数式编程中的副作用概念

    上述的factorial函数有副作用吗?

    答:很显然是有的。函数内部与外界产生了可见的交互,外界result值在函数内部被修改了。而且第一次调用factorial(2) 返回值为 3,第二次调用返回值为6。对于统一输入不能总返回同一结果。这种副作用是被函数式编程思想所排斥的,与外界的交互使得factorial具有不确定性。

    接下来我们看一下另一个例子?

    聊一聊函数式编程中的副作用概念

    那么问题来了,这次factorial有副作用吗?

    答:有副作用,因为for每次执行的时候都会改变factorial的返回值,result在不断改变。

    但是即使这样,factorial(2) 也可以用一个值代替,如果把factorial看作一个黑盒子,从外部我们是看不到副作用的。每次的输入x = 2,总会有固定的返回值3。

    换句话说,该函数是具有确定性的,我们说的功能有局部副作用,但此功能的用户并不关心,因为它没有破坏我们的替代模式。因此,即使具有局部副作用,该函数也是纯净的。这也是上面为什么说“产生了可见的交互”,很显然这句话就是这么严谨,如果见不到,依然是纯的。

    在函数式编程开发中,可以用一些技巧,比如利用容器,把一些副作用控制在局部以达到的目的。

    举一些副作用的典型例子

    想了想还是在这里立举一些典型有副作用的例子,通过例子可以更好的理解这种思想。

    1、与外界交互的。

    聊一聊函数式编程中的副作用概念

    2、调用I/O的 聊一聊函数式编程中的副作用概念

    3、从函数范围之外检索值 聊一聊函数式编程中的副作用概念

    4、磁盘检索 聊一聊函数式编程中的副作用概念

    5、抛出异常

    聊一聊函数式编程中的副作用概念

    END

    函数式编程的副作用被隔离后,剩下的就是纯作用,也就是纯函数,通过pointfree思想执行。下篇见~

    这篇文章终究阐述的是一种思想,虽然全篇举例都举了比较简单的例子,但是思想是一样的。我希望通过一些白话,而不是大篇的官方词语来阐述某种思想。这样的话对读者来说更加容易理解。

    思想不一样的话,我们的代码整体都会变化,比如面向过程、面向对象、面向切片、面向结果...等等

    项目都是一些代码片段搭建起来的,所以我们研究的都是比较小的代码片段。以小见大。

    往期文章推荐

    • 《聊一聊函数式编程中的Hindley-Milner》
    • 《聊一聊函数式编程中的数学》
    • 《拖拽组件:React-DnD用法及源码解析》

    起源地下载网 » 聊一聊函数式编程中的副作用概念

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元