• 函数柯里化详解


    什么是函数柯里化

    柯里化(Currying)又称部分求值,一个柯里化的函数首先会接收一些参数,接收了这些参数后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。

    柯里化是一种函数的转换,它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)或者f(a, b)(c)或者f(a)(b, c)

    通俗的来说:固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数。核心思想是把多参数传入的函数拆成一个个的单参数(或部分)函数,内部再返回调用下一个单参数(或部分)函数,依次处理剩余的参数。有点类似俄罗斯套娃,一层包一层

    备注:柯里化不会调用函数。它只是对函数进行转换。

    函数柯里化示例

    我们先用以下的例子来解释普通函数和柯里化之后的函数有什么区别:

    比如,我们要实现一个日志打印的功能,日志打印,一般输出格式是时间+项目名+信息,如2022-07-29 xxx后台管理系统 mm接口异常,要实现这个功能,分别需要时间、项目名、信息三个参数。接下来我们分别用普通函数的写法和柯里化函数的写法,来实现这一功能

    1. 普通函数:
      普通函数就是三个参数:date, project, message

      // 参数:date, project, message
      const log = (date, project, message) => {
        return `${date} ${project} ${message}`
      }
      
      const logMsg = log('2022-07-29', 'xxx后台管理系统', 'mm接口异常');
      console.log(logMsg) // 输出 2022-07-29 xxx后台管理系统 mm接口异常
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    2. 函数柯里化
      通常来说,输出日志,一般当天日期是不变的,同一个项目的项目名也是不变的(不过不同的项目名是变化的),唯有信息是时刻变化,那么我们可以将日期这个参数存储起来,这样就不用每次都传日期;当遇到同一个项目的时候,也可以把项目名这个参数存起来,不用每次都传项目名;接下来调用只需要传信息这个参数即可

    如下,我们将函数拆成了一个个的单参数函数,再通过俄罗斯套娃的形式返回出去,这样我们就不用每次调用函数的时候都去反复传递这些相同的参数了,而且还能依据不同情况下,组合出不同的参数

    现在,sameDateLog是具有固定date参数的函数,sameDateProjectNameLog是具有固定date、projectName参数的函数,换句话说,sameDateLog、sameDateProjectNameLog都是更简短的“偏应用函数(partially applied function)”或“偏函数(partial)”。

    const log = (date) => {
      
      return (projectName) => {
        
        return (message) => {
    
          return `${date} ${projectName} ${message}`
    
        }
      
      }
    
    }
    
    
    /* 如果日期、项目名、信息都不同的情况下输出日志 */
    // 日期为“2022-07-29”,项目名为“A项目”,输出日志
    const logMsg1 = log('2022-07-29')('A项目')('接口报错');
    console.log(logMsg1); // 打印 2022-07-29 A项目 接口报错
    // 日期为“2022-07-29”,项目名为“A项目”,输出日志
    const logMsg2 = log('2022-08-01')('B项目')('接口成功');
    console.log(logMsg2); // 打印 2022-08-01 B项目 接口成功
    
    
    /* 如果日期相同,项目名、信息不同的情况下输出日志 */
    const sameDateLog = log('2022-07-29');
    // 项目名为“A项目”,输出日志
    const logMsg3 = sameDateLog('A项目')('接口异常');
    console.log(logMsg3); // 打印 2022-07-29 B项目 接口异常
    // 项目名为“B项目”,输出日志
    const logMsg4 = sameDateLog('B项目')('接口超时');
    console.log(logMsg4); // 打印 2022-07-29 B项目 接口超时
    
    
    /* 如果日期、项目名相同,信息不同的情况下输出日志 */
    const sameDateProjectNameLog = log('2022-07-29')('A项目');
    // 输出日志
    const logMsg5 = sameDateProjectNameLog('网络异常')
    console.log(logMsg5); // 打印 2022-07-29 A项目 网络异常
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    实现一个函数,将普通函数柯里化

    Function curry(fn,args){
        var args = args || [];
        return function(){
            let _args = args.concat([…argunments]);
            if(fn.length>_args.length){
                return curry.apply(this,fn,_args)
            }
            else{
                return fn.apply(this,_args)
            }
        }
    }
    
    // 测试
    function sum(a,b,c) {
        return a+b+c;
    }
    let sumFn = curry(sum);
    console.log(sumFn(1)(2)(3)); //6
    console.log(sumFn(1)(2, 3)); //6
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    函数柯里化的优缺点

    优点:

    1. 柯里化之后,我们没有丢失任何参数:log 依然可以被正常调用。
    2. 我们可以轻松地生成偏函数,例如用于生成今天的日志的偏函数。
    3. 入口单一。
    4. 易于测试和复用。

    缺点:

    1. 函数嵌套多
    2. 占内存(因为本质是配合闭包实现的)
  • 相关阅读:
    python实现三维应力云图
    基于混合深度学习的多类型低速率DDoS攻击检测方法
    六氟化硫SF6断路器的运行维护、泄漏处理及气体在线监测
    springboot自定义starter集成controller、Dao
    云计算行业这些热点事件透露了哪些玄机?
    Git学习(3):Git分支操作
    Debezium日常分享系列之:Debezium 2.4.0.Final发布
    信息系统项目管理师必背核心考点(二十四)WBS分解的原则
    Windows10神州网信版的远程桌面开启
    Java进阶(JVM调优)——阿里云的Arthas的使用 & 安装和使用 & 死锁查找案例,重新加载案例,慢调用分析
  • 原文地址:https://blog.csdn.net/Boale_H/article/details/126058783