Curry - Part 5 of 函数式编程


  • administrators

    Curry (咖喱)函数 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。如果你不知道我在说什么,没关系,一步一步来:
    首先看一个普通函数:

    function person = (name, height, weight) {
      return name + '身高' + height + ', 体重' + weight;
    }
    

    用ES6箭头函数可以简写为:

    const person = (name, height, weight) =>
      name + '身高' + height + ', 体重' + weight;
    
    console.log(person('Tom', '1米78', '150公斤'));
    //Tom身高1米78, 体重150公斤
    

    如果你不知道为什么可以这么写,请查看[这里]。(https://j4fun.com/topic/48/map-arrow函数的简写-part-2-of-函数式编程)
    接下来,我们把以上函数用咖喱函数来表示:

    function curryPersonFunction (name) {
      return function personHeightWeight(height, weight) {
        return name + '身高' + height + ', 体重' + weight;
      }
    }
    

    注意:curryPersonFunction()函数现在只接一个参数name,然后返回一个函数personHeightWeight()。这么一来,我们可以用下面的函数调用来实现上面普通函数需要实现的结果:

    const tom = curryPersonFunction('Tom'); //tom 在这里是一个函数
    console.log(tom('1米78', '150公斤'));
    //Tom身高1米78, 体重150公斤
    

    以上的例子或许不能解释为什么要用Curry函数,但是发挥点想象力,你可能注意到,我们可以用Curry函数把一部分函数单独分离出来,这样就可以重复使用它来提高代码的可读性。

    比如下面这个例子:

    const data = {
        "user": "adam",
        "posts": [
            { "title": "why curry?", "contents": "curry is cool" },
            { "title": "why functional", "contents": "functional is clean" }
        ]
    };
    
    function getObjProp(propName, obj){
      return obj[propName];
    }
    
    const titles = getObjProp("posts", data).map(post => {
      return getObjProp("title", post)
    });
    
    console.log(titles);
    //["why curry?","why functional"]
    

    上面例子里,getObjProp是一个普通函数,它接受两个参数,一个是属性名,另外一个是object,然后返回这个属性的值。如果把它写成curry函数,在配上“级联”函数,比如map,我们就不用每次都传入object了。

    const get = prop => obj => obj[prop];
    const titles = get('posts')(data).map(get('title'));
    

    本章对于codePen:
    例子一:Curry基础
    例子二:Curry和Map的妙用