zoukankan      html  css  js  c++  java
  • 纯函数与函数式编程初探

    纯函数概念

    满足一个条件:输入值确定,输出值就确定的函数

    为什么需要存函数

    非混乱的结果

    例子1

    一个计算扣除所得税后工资功能函数,假设直接扣除20%的比例:

    priate static count(double money){
        return money * 0.8;
    }
    

    上面是普通的函数,下面,我们考虑个人所得税计算税率随着时间变化的问题,如果2020.4.24前是扣除0.2,之后调整为扣除0.15,我们可以在方法加个时间判断:

    priate static count(double money){
        double rate = 0.8
        if(today() > Date(2020.4.24)){
            rate = 0.85;
        }
        return money * rate;
    }
    

    上面这个函数,就不是纯函数,它的输出结果不是完全由输入结果决定的

    非纯函数带来的问题

    上面的那个例子,大概可以看到,非纯函数带来的问题:输出结果并非完全由输入结果确定的,这会使得我们的测试变得很麻烦,因为不同的时间测试的结果可能不一样!我同样的输入参数,今天执行和明天执行,得到的结果不一样,那么,对于函数使用者而言,他回觉得这个函数有问题,毕竟他不知道函数内部实现是怎样的。

    纯函数使得结果可控

    所以,上面就是我们使用纯函数的理由之一:使得结果可控,使得程序的状态是确定的,程序就是需要确定性,同样的参数就应该有同样的结果,而不应该依赖外部的状态。
    所以,上面的例子,我们需要吧时间也作为参数传进来,这样才能保证结果是可控的,状态是确定的:

    priate static count(Date date,double money){
        double rate = 0.8
        if(date > Date(2020.4.24)){
            rate = 0.85;
        }
        return money * rate;
    }
    

    函数式编程与纯函数

    何为函数式编程

    java,c++等语言,基本都是过程式的编程:立足于我怎么做?比如,有个业务场景,我们需要做的是读一批学生数据,找到里面性别是女的学生:

    List<Student> students ;
    List<Student> studentsFemal;
    for(let s in students){
        if("femal".equal(s.sex)){
             studentsFemal.add(s);
        }
    }
    

    上面代码没啥问题,但是我们想,我们日常编程,经常会有这种业务场景:在一堆元素中,查找某些特征的元素,我们能否把这个逻辑抽象出来,封装为一个纯函数呢?答案是肯定可以的(当然,这个用java来不太好搞也不直观,下面是js的代码块):

    let list = [];
    for(let i=0;i<10;i++){
        list.push(i);
    }
    const findItemInList = list => howToFind =>{
        let newList = [];
        for(let item of list){
            howToFind(item) && newList.push(item);
        }
        return newList
    }
    console.log(findItemInList(list)(item =>{
       return item > 5
    }));
    

    就这?函数式编程?就找个元素搞得那么蛋疼?有必要?
    当然,上面那么简单的例子的确是没啥必要,但是主要是想通过上面的例子传递一种思想:我们日常编程中,可以把一些重复的操作,通过函数式编程的思想方法抽象起来,封装成一个所谓的高阶纯函数,以便复用:
    上面例子,我们看64行调用findItemInList方法时,是这样调用的:

    findItemInList(list)(item =>{
       return item > 5
    })
    

    findItemInList(list)执行完成后,返回一个函数,我们通常把这种返回结果是函数的函数,叫做所谓高阶函数,这个高阶函数,是一个通用的、专门用于查找符合某个条件的函数,它是一种逻辑的抽象,而具体的逻辑,我们通过传入一个函数来指定,即:

    (item =>{
       return item > 5
    })
    

    然后就可以得到我们的结果。
    总的来说:findItemInList(list)本身抽象了遍历这个过程,而findItemInList(list)(item =>{return item > 5})则对这个过程进行了调用。在这过程当中,findItemInList(list)绑定了list这个列表(绑定了数据),findItemInList(list)(item =>{return item > 5})在绑定数据的基础上绑定了对数据的操作,这个思想其实和过程式编程有一个非常大的区别就是:

    过程式编程我们找具有某个特征的一些元素的时候,我们是遍历这个列表进行查找,强调怎么做;而函数式编程则是表现出我要做什么:我要找元素(对应findItemInList(list)),这个元素是元素数组中值大于5的元素(对应findItemInList(list)(item =>{return item > 5}))。

    纯函数与函数式编程的联系

    一般而言,我们需要实现函数式编程,我们所封装的方法应该是抽象的,应该是和外部状态无关系的,也就需要是纯函数的,这样才能保证抽象的方法可复用而且输出结果只决定于输入参数。
    其实,js里面本身就有封装好的高阶函数,在一定程度上体现了函数式编程的思想,比如数组的map,filter,reduce等方法。而jdk1.8之后lambada表达式也支撑了函数式编程。所以,总的来说,学习下函数式编程的思想,对于提高我们编程的能力还是很有帮助的,他让我们从另外一个角度去思考如何解决和抽象问题。

    end总结

    当然啦,函数式编程还有很多应用,我上面也只是总结了一些皮毛而已,如果想真的了解函数式编程,可以学习下HasKell等真正的函数式编程语言。

  • 相关阅读:
    asp.net 汉字转拼音类
    NET分页实现及代码
    Web.config配置文件详解(新手必看) (转载)
    偶开通博客啦
    转帖不会乱码的,powershell网络蜘蛛
    ConvertFrom-String 命令研究
    powershell玩转xml之20问
    powershell 判断操作系统版本 命令
    powershell加win的dns服务器,解决网站负载均衡问题
    PowerShell并发控制-命令行参数之四问
  • 原文地址:https://www.cnblogs.com/lcplcpjava/p/12767571.html
Copyright © 2011-2022 走看看