用 javascript 解释 curry

这里讲的curry可能和大多数用Js代码讲解的意思有所不同,这里讲curry的与ramda.js里面的一致

这里是维基百科上对curry的解释

什么是curry

curry就是把多个参数的函数简化为一个参数的函数,我觉得没有比使用类型签名描述这个更清楚的选择了

add:Number -> Number -> Number
  • add函数接收两个参数类型是Number 返回一个参数类型Number
  • 如果只传一个参数呢 Number也就是add(1) 此时add函数并没有执行而是返回一个Number->Number的函数 等第二个Number传进来的时候才会真正的执行以加法函数为例子
function add(a,b){return a+ b}

直接调用 add(2,3) 可以看到函数是两个参数

经过curry

var cadd = curry(add)

此时的 调用 cadd(2)(3) 等同于add(2,3) 可以看到 cadd 的参数是一个 通过返回一个函数来收集另外一个参数 这个就是curry

curry的实现方式

接下来我们实现curry函数

第一种是手工curry

let mul = a => b => c => a * b * c

第二种自动curry

function partial(fn,args){
  return function(){
     var nargs = [].slice.call(arguments)
     return fn.apply(null,args.concat(nargs))
  }
}

function curryN(fn,n){
  return function(){
     var args = [].slice.call(arguments)
     if(n <= args.length ) return fn.apply(null,args)
     return curryN(partial(fn,args),n-args.length)
  }
}

function curry(fn){
  return curryN(fn,fn.length)
}

var mul = curry(function (a,b,c){
  return a * b * c
})

console.log(mul(3)(1)(4))
console.log(mul(3,1,4))
// 12

curry有哪些用途

知道了什么是curry,那么curry有哪些用途呢?

  1. 降低认知函数的难度

curry后的函数参数永远固定且只有一个, 不用考虑 默认参数 可选参数情况的函数了

  1. 增加函数和函数之间的组合性

    假设以下所有函数都是 curry的

map :: (a -> b) -> [a] -> [b]
add ::  Number -> Number  -> Number
var add = curry(function(a,b){
  return a + b;
})
var map = curry(function(fn,xs){
  var r = [];
  for(var i=0;i<xs.length;i++){
    r.push(fn(xs[i]));
  }
  return r;
})

map函数 传入一个 函数 一个数组 返回 数组中每一个元素调用 函数 的返回值 的集合

add函数 传入两个函数 返回 相加之后的结果

现在要把 [1,2,3,4] 每一个元素都加上 10 ,就可以使用组合的方式(fp中叫做pointfree)

map(add(10),[1,2,3,4])

由于add(10) 正好返回一个接收一个参数的函数 放到map中 完美的组合在了一起!

再看个filter的例子

var filter = curry(function(fn,xs){
  var r = []
  for(var i = 0;i<xs.length;i++){
    if(fn(xs[i])){
      r.push(xs[i])
    }
  }
  return r;
})

var lt = curry(function(a,b){
  return a < b
})

filter(lt(10),[1,2,90,10,77])

输出大于10的数组 [90,77]

常见的问题

  • 带可选参数或者默认参数的函数 可以进行curry吗 ?
    • 答: 不可以
点击这里查看原文
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值