概念

# 概念

Haskell Brooks Curry

使用柯里化解决纯函数案例中硬编码的问题

// 硬编码
function checkAge (age) {
  let min = 18
  return age >= min
}

// 普通纯函数
function checkAge (min, age) {
  return age >= min
}

checkAge(18, 24)
checkAge(18, 20)
checkAge(20, 30)

// 柯里化
function checkAge (min) {
  return function (age) {
    return age >= min
  }
}

// ES6 写法 箭头函数
let checkAge = min => (age => age >= min)

let checkAge18 = checkAge(18)
let checkAge20 = checkAge(20)
checkAge18(24)
checkAge18(20)

柯里化 (Currying): 当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数以后永远不变) 然后返回一个新的函数接收剩余的参数,返回结果

# lodash 中的柯里化函数

_.curry(func)

  • 功能:创建一个函数,该函数接收一个或多个 func 的参数,如果 func 所需要的参数都被提供则执行 func 并返回执行的结果。否则继续返回该函数并等待接收剩余的参数。
  • 参数:需要柯里化的函数
  • 返回值:柯里化后的函数
const _ = require('lodash')
// 要柯里化的函数
function getSum (a, b, c) {
  return a + b + c
}
// 柯里化后的函数
let curried = _.curry(getSum)

// 测试
curried(1, 2, 3)
curried(1)(2)(3)
curried(1)(2, 3)
// 一元的函数
curried(1, 2)(3)

案例

const _ = require('lodash')

const match = _.curry(function (reg, str) {
  return str.match(reg)
})

const haveSpace = match(/\s+/g) // 全局匹配任意多个空白字符
const haveNumber = match(/\d+/g) // 全局匹配任意多个数字

console.log(haveSpace('hello world'))
console.log(haveNumber('25$'))

const filter = _.curry(function (func, array) {
  return array.filter(func)
})

console.log(filter(haveSpace, ['John Connor', 'John_Donne'])) // ['John Connor']

const findSpace = filter(haveSpace)

console.log(findSpace(['John Connor', 'John_Donne'])) // ['John Connor']

模拟 _.curry() 的实现

function curry (func) {
  return function curriedFn (...args) {
    // 判断实参和形参的个数
    if (args.length < func.length) {
      return function () {
        // 递归调用curriedFn
        return curriedFn(...args.concat(Array.from(arguments)))
      }
    }
    // 实参和形参个数相同,调用 func,返回结果
    return func(...args)
  }
}

# 总结

  • 柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数
  • 这是一种对函数参数的'缓存'
  • 让函数变的更灵活,让函数的粒度更小
  • 可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能
上次更新: 2022/4/10 21:26:03