FP

2018-12-23  本文已影响14人  lmmy123

偏函数

function partial( fn, ...prevArgs ) {
  return function partialed( ...lastArgs ) {
    return fn( ...prevArgs, ...lastArgs )
  }
}

颠倒实参顺序

function reverseArgs( fn ) {
  return function argsReversed( ...args ) {
    return fn( ...args.reverse() )
  }
}

组合函数

function compose( ...fns ) {
  return function composed(result) {
    let list = fns.slice()
    while( list.length > 0 ) {
      result = list.pop()( result )
    }
    return result
  }
}

组合函数 reduce实现

function compose( ...fns ) {
  let list = fns.slice()
  return list.reverse().reduce( function reducer( fn1, fn2 ) {
      return function composed( ...args ) {
        return fn2( fn1( ...args ) )
      }
  } )
}

pipe(...) VS compose(...)
pipe() 从左向右执行

function pipe( ...fns ) {
  return function piped( result ) {
    let list = fns.slice()
    while( list.length > 0 ) {
      result = list.shift()( result )
    }
    return result
  }
}

右偏函数应用

function partialRight( fn, ...prevArgs ) {
  return reverseArgs(
    partial( reverseArgs( fn ), ...prevArgs.reverse() )
  )
}
function foo(x,y,z) {
  var rest = [].slice.call(arguments, 3)
  console.log(x,y,z,rest)
}
var f = partialRight( foo, 'z:last' )
f(1,2) // 12 'z:last' []
f(1) // 12 'z:last' undefined []

柯理化

function curry( fn, arity = fn.length ) {
  return ( function nextCurried( prevArgs ) {
    return function curried(nextArg) {
      var args = prevArgs.concat( [nextArg] )
      if( args.length >= arity ) {
        return fn( ...args )
      }else{
        return nextCurried( args )
      }
    }
  } )( [] )
}

把空数组[]当做 prevArgs的初始实参集合,接收的nexArg同 prevArgs组成 args,当args.length小与 arity(原函数fn(...)被定义和期望的形参数量),返回另一个curried函数,用来接收下一个nextArg实参

function add(x,y) {
  return x + y
}
// 偏函数
[1,2,3].map( partical(add,2) ) //[3,4,5]
// 柯理化
[1,2,3].map( curry(add)(2) ) // [3,4,5]

松散的柯理化
可以多参,并且可以超过预设参数 长度
var curryed = looseCurry( add, 5 )
curryed(1)( 2,3 )(4,5)
curryed(1,2)(3,4)(5,6)

function looseCurry( fn, arity = fn.lenght ) {
  return ( function nextCurried( prevArgs ){
    return function curried( ...nextArgs ) {
      var args = prevArgs.concat( nextArgs ) 
      
      if( args.length >= arity ) {
        return fn( ...args )
      }else {
        return nextCurried( args )
      }
    }  
  })( [] )
}

反柯理化
f(1)(2)(3) => g(1,2,3)

function uncurry(fn) {
    return function uncurried( ...args ) {
      var ret = fn;
      for( let i=0;i<args.length;i++ ) {
        ret = ret( args[i] )
      }
      return ret
    }
}
上一篇下一篇

猜你喜欢

热点阅读