美文网首页
函数式编程-函数运算(2)

函数式编程-函数运算(2)

作者: Fantast_d2be | 来源:发表于2021-07-28 22:47 被阅读0次

柯里化

  • 使用柯里化解决上一个案例中硬编码的问题
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)
  • 柯里化(Curring):
    • 当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数以后永远不变)
    • 然后返回一个新的函数接收剩余的参数,返回结果

lodash中的柯里化函数

  • _.curry(func)
    • 功能:创建一个函数,该函数接收一个或多个func的参数,如果func所需要的参数都被提供则执行func并返回执行的结果。否则继续返回该函数并等待接收剩余的参数。
    • 参数:需要柯里化的函数
    • 返回值:柯里化后的函数
  • 案例
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']))

const findSpace = filter(haveSpace)
console.log(findSpace(['John Connor', 'John_Donne']))
  • 模拟 _.curry() 的实现
function curry(func) {
  return function curriedFn (...args) {
    // 判断实参和形参的个数
    if(args.length < func.length) {
      return function() {
        return curriedFn(...args.concat(Array.from(arguments)))
      }
    }
    return func(...args)
  }
}

总结

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

函数组合

  • 纯函数和柯里化很容易写出洋葱代码h(g(f(x)))
// 获取数组的最后一个元素再转换成大写字母
_.toUpper(_.first(_.reverse(array)))
  • 函数组合(compose):如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并成一个函数

    • 函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结股票
    • 函数组合默认是从右到左执行
    // 组合函数
    function compose (f, g) {
      return function (x) {
        return f(g(x))
    } }
    function first (arr) {
      return arr[0]
    }
    function reverse (arr) {
      return arr.reverse()
    }
    // 从右到左运行
    let last = compose(first, reverse) 
    console.log(last([1, 2, 3, 4]))
    
  • 函数组合可以让我们把细粒度的函数重新组合生成一个新的函数

  • 模拟实现组合函数方法

// 多函数组合
function compose(...fns) {
  return function (value) {
    return fns.reverse().reduce(function (acc, fn) {
      return fn(acc)
    },value)
  }
}
  • 函数的组合要满足结合律

    • 我们既可以把g和h组合,还可以把f和g组合,结果都是一样的
    // 结合律(associativity)
    let f = compose(f, g, h)
    let associative = compose(compose(f, g), h) == compose(f, compose(g, h)) // true
    

调试

const _ = require('lodash')
const trace = _.curry((tag, v) => { console.log(tag, v)
return v
})
const split = _.curry((sep, str) => _.split(str, sep)) 
const join = _.curry((sep, array) => _.join(array, sep))
const map = _.curry((fn, array) => _.map(array, fn))
const f = _.flowRight(join('-'), trace('map 之后'), map(_.toLower), trace('split 之后'), split(' '))
console.log(f('NEVER SAY DIE'))

Point Free

Point Free:我们可以把数据处理的过程定义成于数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

  • 不需要指明处理的数据
  • 只需要合成运算过程
  • 需要定义一些辅助的基本运算函数
const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.split(' '))
  • 案例演示
// 非 Point Free 模式
// Hello World => hello_world function f (word) {
return word.toLowerCase().replace(/\s+/g, '_'); }
// Point Free
const fp = require('lodash/fp')
const f = fp.flowRight(fp.replace(/\s+/g, '_'), fp.toLower) 
console.log(f('Hello World'))
  • 使用 Point Free 的模式,把单词中的首字母提取并转换成大写
const fp = require('lodash/fp')
const firstLetterToUpper = fp.flowRight(join('. '),
fp.map(fp.flowRight(fp.first, fp.toUpper)), split(' '))
console.log(firstLetterToUpper('world wild web'))

相关文章

  • Scala面试题

    scala语言的特点: 集成了面向对象和函数式编程 函数式编程是将计算机的运算视为函数运算 链式编程 Scala中...

  • 【Scala】Scala函数式编程初探

    函数式编程 函数式编程是种编程典范,它将电脑运算视为函数的计算。函数编程语言最重要的基础是 λ 演算(lambda...

  • 20160905兄弟连笔记

    函数式编程是种编程范式,它将电脑的运算视为函数的计算。和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。...

  • 函数式编程学习笔记

    函数式编程 函数式编程的核心思想是把运算过程抽象成函数,编程过程中面向函数进行编程 一、纯函数:相同的输入永远会得...

  • 函数式编程-函数运算(2)

    柯里化 使用柯里化解决上一个案例中硬编码的问题 柯里化(Curring):当一个函数有多个参数的时候先传递一部分参...

  • 异常、try 语句、raise 语句、bytes和bytearr

    昨天回顾id(x) 函数is / is not 运算符函数式编程高阶函数map(函数, 可迭代对象) # 返回生...

  • 函数式编程的概念

    函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculu...

  • Java基础篇(05):函数式编程概念和应用

    一、函数式概念 函数式编程是一种结构化编程的范式,主要思想是把运算过程尽量写成系列嵌套的函数调用。函数编程的概念表...

  • 函数式编程小思考2 笔记

    函数式编程与面向对象编程的比较 什么是函数式编程?是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程...

  • JavaScript 函数式编程

    一、什么是函数式编程函数编程是一种编程范式,主要利用函数把运算过程封装起来,通过组合各种函数来计算结果。 函数编程...

网友评论

      本文标题:函数式编程-函数运算(2)

      本文链接:https://www.haomeiwen.com/subject/mxvtvltx.html