js如何用一句代码实现函数的柯里化(ES6)

更新日期: 2021-04-27阅读: 685标签: 柯里化

柯里化是干什么的?首先看看下面这个函数

let store = (a,b,c) => "这是你的七仔面"  
//函数就好像一个小卖部,一碗七仔面要三张软妹币:a,b,c (五个参数)

那函数柯里化是什么?就是我们买面吃的过程可能是这样:

let curryStore = curry(store)  //刚刚的小卖部被柯里化了

//最佳状况
curryStore(1,5,1)// 老板,刚好!不用找了,刚好七块钱。老板: "这是你的七仔面"  

//偶尔出现的情况
let boss = curryStore(5) //老板,这五块钱你先拿着,我找找有没有一块钱。老板:……
boss = boss(1) //有了老板,这一块钱你先拿着,我找找还有没有一块钱。。老板:……
boss(1) //哈哈,终于找到了,给!老板:"这是你的七仔面"  

curryStore(5)(1)(1) //等价于上诉情况

所以这里我们可以看到,函数柯里化,是可以用来慢慢凑齐参数,延迟函数的执行。(先分期交钱,后交货!)

做个题

现在,我们的目标是实现一个curry 函数,达到以下使用效果:
在给到足够的参数时,执行函数。不够参数的时候则返回一个新的curry函数。

let curryPlus = curry((a,b,c) => a+b+c)  //这里给到一个有三个参数的函数

curryPlus(1)(2)(3) //返回 6
curryPlus(1)(2,3) //返回 6
curryPlus(1,2)(3) //返回 6

let x = curryPlus(1)(2) //喂,怎么才两个参数?返回一个curry函数(已经带了两个参数)
x(1) //返回 4
x(2) //返回 5

作为一个js很厉害的人,这种问题用一行代码解决不是问题,问题是我没那么厉害。。。
于是,我们先从土方法说起吧orz

按照curry的用法,原理是返回了一个函数,这个函数的参数个数不确定(你可能同时掏出两张一块钱),于是我们可以运用不定参数的写法:

const curry = (fn) => {
    return (...args) =>{  //不定参数,想给多少给多少
        //给钱交货环节
    }
}

柯里化函数需要记住你已经给过他的参数,如果没给的话,则默认为一个空数组:

const curry = (fn,arr=[]) => {  //arr数组用于记录已有参数
    return (...args) =>{   
        //给钱交货环节
    }
}

接下来每次调用的时候,需要检查参数是否给够,如果够了,则执行fn,没有的话则返回一个新的curry函数,将现有的参数塞给他:

const curry = ( fn, arr = []) => {
    return (...args) => { 

        //判断参数总数是否和fn参数个数相等
        if([...arr, ...args].length === fn.length){
            return fn(...arr, ...args) //拓展参数,调用fn
        }else{
            return curry(fn,[...arr, ...args]) //迭代,传入现有的所有参数
        }

    }
}

到这里,其实我们已经实现了curry函数。

接下来就是要看看怎么写才能更简洁。
首先,中间的代码可以写成一个立即执行函数,省掉一些...arr, ...args:

const curry = ( fn, arr = []) => {
    return (...args) => { 

        return ( a => {   //a是一个数组
            if(a.length === fn.length) {
                return fn(...a)
            }else{
                return curry(fn, a)
            }
        })([...arr, ...args])  //这里把arr和args摊开成一个数组赋值给a

    }
}

if语句可以缩减成三元表达式,也可以省掉很多字啦:

const curry = ( fn, arr = []) => {
    return (...args) => { 

        return ( a => { 

            return a.length === fn.length ?  fn(...a) : curry(fn, a)

        })([...arr, ...args])  

    }
}

最后,既然函数里啥事都没干,就只是return的话,不妨使用箭头函数最省的写法 input => output, 把return和大括号都给省了:

const curry = ( fn, arr = []) => {
    return (...args) => { 
        return ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args])   //先折叠一层
    }
}

再折叠:

const curry = ( fn, arr = []) => {
    return (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args])   //再折叠
}

收工了收工了:

const curry = ( fn, arr = []) => (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args]) 
//衣服给您叠好了

拿去试试:

const curry = ( fn, arr = []) => (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args])
let curryPlus = curry((a,b,c,d)=>a+b+c+d)

curryPlus(1,2,3)(4) //返回10
curryPlus(1,2)(4)(3) //返回10
curryPlus(1,2)(3,4) //返回10

当然了,柯里化函数的主要作用还是延迟执行,执行的触发条件不一定是参数个数相等,也可以是其他的条件,例如参数个为0的情况,那么我们需要对上面curry函数稍微做修改:

const curry = ( fn, arr = []) => (...args) => ( (a,b) => b.length === 0? fn(...a) : curry(fn, a))([...arr, ...args],[...args])
let curryPlus = curry((...x)=>x.reduce((a,b)=>a+b))

curryPlus(1) //返回一个函数
curryPlus(1)(2) //返回一个函数

//遇到参数个数为0的情况才执行
curryPlus(1)(2)(4)() //返回7
curryPlus(1,2)(4)() //返回7

链接: https://fly63.com/article/detial/11426

JavaScript函数柯里化

理论计算机科学中,柯里化提供了在简单的理论模型中,比如:只接受一个单一参数的lambda演算中,研究带有多个参数的函数的方式。 函数柯里化的对偶是Uncurrying,一种使用匿名单参数函数来实现多参数函数的方法。

javascript偏函数应用与柯里化的区别

很多刚刚了解函数式编程的人会对偏函数应用(partial application)和柯里化(currying)之间的区别感到困惑。实际上,直到现在也很少在 JavaScript 中看到柯里化的实际使用,许多叫curry()的工具函数并不是柯里化函数。它们其实是偏函数!

柯里化与反柯里化

柯里化,是一个逐步接收参数的过程。在接下来的剖析中,你会深刻体会到这一点。 反柯里化,是一个泛型化的过程。它使得被反柯里化的函数,可以接收更多参数。目的是创建一个更普适性的函数,可以被不同的对象使用。

js函数柯里化的延伸

如果我们需要设计一个函数来计算每个月的开销,在每天结束之前,我们需要记录当天花费了多少。在月底的时候计算出这个月一共开销了多少? 可以看出在性能上和方式二差不多,但是这样做更加通俗易懂了,当然在实际开发中,我们一般会封装为对象。

js高级函数技巧-函数柯里化

我们经常说在Javascript语言中,函数是“一等公民”,它们本质上是十分简单和过程化的。可以利用函数,进行一些简单的数据处理,return 结果,或者有一些额外的功能,需要通过使用闭包来实现,最后经常会return 匿名函数。

Js柯里化

柯里化(Currying),又称部分求值(Partial Evaluation),是把接收多个参数的函数变成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受剩余的参数而且返回结果的新函数的技术。

javascript实现函数柯里化与反柯里化

把接收多个参数的函数变换成接收一个单一参数(最初函数的第一个参数)的函数,并返回接受剩余的参数而且返回结果的新函数的技术。其由数学家Haskell Brooks Curry提出,并以curry命名。

Js之函数柯里化

最近在社区阅读技术博客的时候偶然间看到了函数柯里化几个字,还有要求手写js函数柯里化,心想是柯里化是什么高级的东西?没听说过啊?就带着问题出发,专门去学习了一下,做了一些整理。

理解Javascript的柯里化

函数式编程是一种如今比较流行的编程范式,它主张将函数作为参数进行传递,然后返回一个没有副作用的函数,说白了,就是希望一个函数只做一件事情。这种编程思想涵盖了三个重要的概念:

函数柯里化详解

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!