• 函数式编程介绍


    本文将描述函数式编程的基本理论,从而让你理解什么是函数式编程,同时也会展示“函数式编程”和“面向对象”这两种不同风格的编程范式之间的区别。本文是函数式编程系列的入门篇,后续文章陆续会发出。

    什么是函数

    函数式编程背后的理论依据是数学,数学函数背后有一系列有意思的特点,而函数式编程语言则试图模拟这些特性。
    让我们先来看一个简单的数学函数:

    y =  x + 1
    

    这个数学函数的意图是显而易见的,给定一个变量x然后返回x + 1, 上面的数学函数用C#来表示:

    public int Add1(int x)
    {
        return x + 1;
    }
    

    数学函数跟我们用命令式语言编写的函数相比有两个明显的区别:

    • 同一个输入在数学函数里总能得到相同的返回值
    • 数学函数没有副作用
    • 输入值和输出值是不变的(immutable)

    这三个区别具体是什么意思呢?

    同一个输入在数学函数里总能得到相同的返回值

    在命令式语言(imperative programming)中,我们总是在函数内部做一些计算和处理,然后返回最终结果。在数学函数中没有计算和处理,你可以认为数学函数的返回值是对输入值的一一映射。上面提到的数学函数极端定义如下:

    int Add1(int x)
    { 
       switch (x)
       {
       case 0: return 1;
       case 1: return 2;
       case 2: return 3;
       case 3: return 4;
       //...
       }
    }
    

    当然现实环境中我们不会写出这样的代码,但是数学函数的思想是类似的,里面没有对事情的处理逻辑。
    关于命令式语言和声明式语言的区别看这里:命令式语言和声明式语言的区别

    数学函数没有副作用

    数学函数所做的事就是根据每一个输入返回不同的输出,整个过程没有对输入值做任何改变,在返回输出的过程中也没有对其他的任何环境造成影响,在函数式语言里这样的函数被称为纯函数

    输入值和输出值是不变的

    immutable使得代码更加具有预测性,考虑下面的代码:

    public int Add1(int x)
    {
        x = 2;
        return x + 1;
    }
    
    public void InvokeAdd1()
    {
        var x = 10;
        var y = Add1(x);
    
        Console.WriteLine($"x={x}, y={y}");
    }
    

    你试图在Add1函数中实现y = x + 1,但是由于失误将x的值改为了2,从而导致了一个bug,immutable则强制你无法修改x的值,一旦初始化就不能再修改。显然C#默认是mutable的,但在常见的函数式语言中,变量声明式immutable的,比如在F#中将x初始化为6然后再修改为7会编译出错:

    let x = 6
    x <- 7
    

    作为一个修炼命令式语言多年的开发者也许会内心充满疑问,无法修改变量真的靠谱?答案是肯定的,在后面的文章中将会展示这种用法。

    纯函数带来的好处

    看似不起眼的三个特点实际上会带来非常强大的益处,所以函数式编程语言则试图把这三个特性带到他们的设计当中。

    得益于纯函数的这种特点,对同一个输入无论你重复调用多次,都会返回同样的结果,并且没有副作用,因此:

    • 所有的调用可以使并行的。 假如你想用1到10000之间的数字去调用Add1函数,你可以把这些计算过程分配到10个不同的CPU上并行执行,由于所有的调用都是没有副作用的,所以你不需要使用命令式语言中的锁机制就能完成任务;
    • 懒加载成为现实,你可以在真正需要结果的时候去执行计算,因为你可以保证在任何时刻对同一个输入返回的结果总是相同的
    • 你可以对函数的计算结果进行缓存,因为相同的输入总能得到相同的结果,所以可以轻而易举的对函数增减缓存功能

    后续文章即将发出,请想了解函数式编程的童鞋支持并关注。

    如果您觉得本文对你有用,不妨帮忙点个赞,或者在评论里给我一句赞美。我们正在使用.NET Core / Azure / Xamarin等技术开发基于互联网和移动应用平台上的各种新产品和商业服务。我们的目标是通过举办各种分享活动,交流开发心得和经验来推动.NET技术栈在西安乃至西北地区的发展。我们是一个开发和自由的社区,欢迎您加入西安.NET社区,微信账号:dotNetXA 欢迎您持续关注我的博客

  • 相关阅读:
    【原创翻译】给前端小白的现代JavaScript工作流程详解 | Modern JavaScript Explained For Dinosaurs
    JavaScript音频可视化
    CSS两种布局记录
    飞桨|PaddlePaddle YoloV3学习笔记
    飞桨|PaddlePaddle第二周学习笔记|卷积神经网络、计算机视觉相关知识
    求所有不重复路径, Unique Paths | 换硬币问题 LeetCode题解(四)
    最大子数组,Maximum Subarray| Best Time to Buy and Sell Stock, LeetCode题解(三)
    合并k个有序链表, LeetCode题解(二)
    TwoSum, ThreeSum, 数字链表相加, LeetCode题解(一)
    最长公共子序列、最长重复子串
  • 原文地址:https://www.cnblogs.com/xiandnc/p/9256503.html
Copyright © 2020-2023  润新知