函数式编程核心概念-柯里化(Currying)

362 阅读2分钟

我们先从一个使用柯里化解决硬编码问题的案例开始了解柯里化的概念:

// 存在硬编码问题的函数
function checkAge (age) {
    const min = 18
    return age >= min
}
console.log(checkAge(20))

// 使用普通纯函数解决方案
function checkage (min, age) {
    return age >= min
}
console.log(checkAge(18, 20))

// 使用闭包配合柯里化解决方案
function checkAge (min) {
    return function (age) {
        return age >= 18
    }
}
const checkAge18 = checkAge(18)
console.log(checkAge18(20))

柯里化概念:

  1. 当一个函数有多个参数的时候,先传递一部分参数(这部分参数以后永不改变)调用它;
  2. 然后返回一个新的函数接受剩余参数,返回结果。

Lodash 中的柯里化方法 _.curry(func):

  • 功能:创建一个函数,该函数接受一个或多个func的参数,如果func所需的参数都被提供则执行func并返回执行结果。否则,继续返回该函数并等待剩余参数。
  • 目的:将一个多元函数转换成一个一元函数。
  • 参数:需要柯里化的函数。
  • 返回值:柯里化后的函数。

案例:

const _ = require('lodash')
function sum (a, b, c) {
    return a + b + c
}
const curriedSumFunc = _.curry(sum)
curriedSumFunc(1)(2)(3)
curriedSumFunc(1, 2)(3)
curriedSumFunc(1)(2, 3)
curriedSumFunc(1, 2, 3)

const match = _.curry((reg, str) => str.match(reg))
const filter = _.curry((func, arr) => arr.filter(func))
const haveSpace = match(/\s+/g)
const haveNumber = match(/\d+/g)
const hasSpaces = filter(findSpace)
const hasNumber = filter(findNumber)
const arr = ['Donald Trump', 'JoeBidden', 'Leo2020']
console.log(hasSpaces(arr))
console.log(hasNumber(arr))

柯里化原理模拟:

/** * 有形参函数柯里化实现 * @param {*} func 被柯里化函数 * @return {function curryed(params) { }} 柯里化后的函数 * 实现原理判断实参与形参的个数是否相同,分为两种情况 * 1、当实参个数小于形参个数时则缓存现有实参,继续等待剩余参数; * 2、当实参个数大于等于形参个数时,则直接执行函数; * 要点: * 1、获取函数的形参个数:利用函数的 length 属性 * 2、获取函数的实参:使用函数的 arguments 属性 * 3、使用闭包与使用剩余参数的形式缓存外层函数的形参 */function currying (func) {    return function curryed (...arg) {        if (arguments.length < func.length) {            return function () {                return curryed(...arg, ...arguments)            }        }        return func(...arguments)    }} const forCurry = currying(sum) const result = forCurry(1, 2) console.log(result(1))

总结:

柯里化可以让我们给一个函数传递较少的参数,得到一个已经记住了某些固定参数的新函数,者就是柯里化的核心。在柯里化内部就是使用闭包,对函数的参数进行缓存。柯里化让函数变得更灵活,因为我们可以通过一个函数生成一些细粒度更小的函数。这么做的目的是为了在后续函数组合的时候在使用。柯里化可以把多元函数转换成一元函数,目的是可以组合使用函数产生强大的功能。