资讯专栏INFORMATION COLUMN

函数式编程(一)

罗志环 / 2998人阅读

摘要:函数式编程的准则不依赖于外部的数据,而且也不改变外部数据的值,而是返回一个新的值给你。函数式编程利用纯函数的无状态性,它的好处非常多结果可预期利于测试利于复用利于并发,但一个系统工程的代码,是不可能全部采用纯函数来写的。

什么是函数式编程

函数式编程是一种编程范式,常见的编程范式有以下三种:

命令式编程

声明式编程

函数式编程

函数式编程的本质是将计算描述为一种表达式求值。在函数式编程中,函数作为一等公民,可以在任何地方定义(在函数内或函数外),可以作为函数的参数和返回值,可以对函数进行组合。

函数式编程的准则:不依赖于外部的数据,而且也不改变外部数据的值,而是返回一个新的值给你。看个简单的例子:

    // 非函数式的例子
    let count = 0;
    function increment() {
        count++; // 依赖于函数外部的值,并改变了它的值
    }
    
    // 函数式的例子
    function increment(count) {
        return count++;
    }
为什么采用函数式编程

函数式编程不依赖外部的状态也不修改外部的状态,函数调用的结果不依赖调用的时间和位置,这些写代码容易进行推理,不易犯错,而且单测和调试都更简单。即函数编程采用纯函数。

纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。

副作用可能包含,但不限于:

更改文件系统

往数据库插入记录

发送一个 http 请求

可变数据

打印/log

获取用户输入

DOM 查询

访问系统状态

副作用是在计算结果的过程中,系统状态的一种变化,或者与外部世界进行的可观察的交互。

纯函数的好处:

纯函数能根据输入来做缓存(memoize技术)

    const memoize = function(f) {
        const cache = {};
        return function() {
            const argStr = JSON.stringify(arguments);
            
            if (!cache[argStr]) {
                cache[argStr] = f.apply(f, arguments);
            }
            
            return cache[argStr];
        }
    }

可移植性/自文档化
纯函数的输出只依赖与它的输入,依赖很明确,易于理解。由于纯函数不依赖它的上下文环境,因此我们可以轻易的把它移植到任何地方运行它。

可测试性
我们不必在每次测试前都去配置和构造初始环境,只需简单给函数一个输入,然后断言它的输出就好了。

合理性
由于纯函数总是能够根据相同的输入返回相同的输出,所以它们就能够保证总是返回同一个结果,这也就保证了引用透明性。

并行执行
我们可以并行运行任意纯函数。因为纯函数根本不需要访问共享的内存,而且根据其定义,纯函数也不会因副作用而进入竞争态。
并行代码在服务端 js 环境以及使用了 web worker 的浏览器那里是非常容易实现的,因为它们使用了线程(thread)。不过出于对非纯函数复杂度的考虑,当前主流观点还是避免使用这种并行。

实现函数式编程的技术

这里我们先不展开这些技术的细节内容,本文我们先侧重于对函数式编程有一个整体上的认识,具体的技术细节我们将在下一章展开。

curry(柯里化)

compose(代码组合)

Monad(Monad就是一种设计模式,表示将一个运算过程,通过函数拆解成互相连接的多个步骤。你只要提供下一步运算所需的函数,整个运算就会自动进行下去。)

如何正确看待函数式编程

我们先来看以下几种观点:

你这段代码用了 for 循环,这是过程式的。为了优雅,你应该写成函数式的。

你这段代码有副作用,这是肮脏的。为了纯净性,你应该把 IO 包在 Monad 里。

你这段代码用了 class,这是面向对象的。为了无状态,你应该写成高阶函数。

我想说的是这种偏激的观点是不正确的,我们不应该把函数式编程和命令式编程对立起来,我们更多的时候需要考虑的是技术的适用场景。函数式编程写起代码来,有一定的难度,如果一个团队的整体水平达不到,那么写代码的质量和效率还不如采用命令式编程好。函数式编程利用纯函数的无状态性,它的好处非常多(结果可预期、利于测试、利于复用、利于并发),但一个系统工程的代码,是不可能全部采用纯函数来写的。当我们越贴近业务,我们就离纯函数与无状态越远。

函数式编程非常重要,学习它我们能打开我们的思维方式,使用它也有很多好处,但它也有一些局限,我们应该客观看待。保持开放的心态,根据实际场景选择合适的技术,是一个工程师基本的素养。

参考资料

https://llh911001.gitbooks.io...
http://www.ruanyifeng.com/blo...
https://coolshell.cn/articles...
https://www.zhihu.com/questio...
https://zhuanlan.zhihu.com/p/...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102564.html

相关文章

  • SegmentFault 技术周刊 Vol.16 - 浅入浅出 JavaScript 函数编程

    摘要:函数式编程,一看这个词,简直就是学院派的典范。所以这期周刊,我们就重点引入的函数式编程,浅入浅出,一窥函数式编程的思想,可能让你对编程语言的理解更加融会贯通一些。但从根本上来说,函数式编程就是关于如使用通用的可复用函数进行组合编程。 showImg(https://segmentfault.com/img/bVGQuc); 函数式编程(Functional Programming),一...

    csRyan 评论0 收藏0
  • 编程函数编程

    摘要:声明式编程一种编程范式,与命令式编程相对立。常见的声明式编程语言有数据库查询语言,正则表达式逻辑编程函数式编程组态管理系统等。函数式编程,特别是纯函数式编程,尝试最小化状态带来的副作用,因此被认为是声明式的。 编程范式与函数式编程 一、编程范式的分类 常见的编程范式有:函数式编程、程序编程、面向对象编程、指令式编程等。在面向对象编程的世界,程序是一系列相互作用(方法)的对象(Class...

    noONE 评论0 收藏0
  • 翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数编程》- 第 1 章:

    摘要:所以我觉得函数式编程领域更像学者的领域。函数式编程的原则是完善的,经过了深入的研究和审查,并且可以被验证。函数式编程是编写可读代码的最有效工具之一可能还有其他。我知道很多函数式编程编程者会认为形式主义本身有助于学习。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson - 《You-Dont-Know-JS》作者 关于译者:这是一个流淌着沪江血液...

    omgdog 评论0 收藏0
  • javascript 函数编程思想

    摘要:今天这篇文章主要介绍函数式编程的思想。函数式编程通过最小化变化使得代码更易理解。在函数式编程里面,组合是一个非常非常非常重要的思想。可以看到函数式编程在开发中具有声明模式。而函数式编程旨在尽可能的提高代码的无状态性和不变性。 最开始接触函数式编程的时候是在小米工作的时候,那个时候看老大以前写的代码各种 compose,然后一些 ramda 的一些工具函数,看着很吃力,然后极力吐槽函数式...

    YPHP 评论0 收藏0
  • JavaScript 函数编程

    摘要:函数式编程的哲学就是假定副作用是造成不正当行为的主要原因。函数组合面向对象通常被比喻为名词,而函数式编程是动词。尾递归优化函数式编程语言中因为不可变数据结构的原因,没办法实现循环。 零、前言 说到函数式编程,想必各位或多或少都有所耳闻,然而对于函数式的内涵和本质可能又有些说不清楚。 所以本文希望针对工程师,从应用(而非学术)的角度将函数式编程相关思想和实践(以 JavaScript 为...

    hoohack 评论0 收藏0

发表评论

0条评论

罗志环

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<