zoukankan      html  css  js  c++  java
  • JavaScript Patterns 4.10 Curry

    Function Application

    apply() takes two parameters: the first one is an object to bind to this inside of the function, the second is an array or arguments, which then becomes the array-like arguments object available inside the function. If the first parameter is null, then this points to the global object, which is exactly what happens when you call a function that is not a method of a specific object. 

    // define a function
    
    var sayHi = function(who) {
    
        return "Hello" + ( who ? ", " + who : "") + "!";
    
    };
    
    // invoke a function
    
    sayHi();
    // "Hello"
    
    sayHi('world');
    // "Hello, world!"
    
    // apply a function
    
    sayHi.apply(null, ["hello"]);
    // "Hello, hello!"
    
    //-----------------------------------------------------------------------
    
    var alien = {
    
        sayHi : function(who) {
    
            return "Hello" + ( who ? ", " + who : "") + "!";
    
        }
    };
    
    alien.sayHi('world');
    // "Hello, world!"
    
    sayHi.apply(alien, ["humans"]);
    // "Hello, humans!"

    In the preceding snippet,  this inside of  sayHi() points to  alien. In the previous example this points to the global object.

    When you have a function that takes only one parameter, you can save the work of creating arrays with just one element:

    // the second is more efficient, saves an array
    
    sayHi.apply(alien, ["humans"]); // "Hello, humans!"
    
    sayHi.call(alien, "humans"); // "Hello, humans!"

     

    Partial Application

    var add = function(x, y) {
    
        return x + y;
    
    };
    
    // full application
    
    add.apply(null, [5, 4]);
    // 9
    
    // partial application
    
    var newadd = add.partialApply(null, [5]);
    
    // applying an argument to the new function
    
    newadd.apply(null, [4]);
    // 9

     

    Here’s no  partialApply() method and functions in JavaScript don’t behave like this by default. But you can make them, because JavaScript is dynamic enough to allow this. The process of making a function understand and handle partial application is called currying.

    // a curried add()
    
    // accepts partial list of arguments
    
    function add(x, y) {
    
        var oldx = x, oldy = y;
    
        if ( typeof oldy === "undefined") {// partial
    
            return function(newy) {
    
                return oldx + newy;
    
            };
    
        }
    
        // full application
    
        return x + y;
    
    }
    
    // test
    
    typeof add(5);
    // "function"
    
    add(3)(4);
    // 7
    
    // create and store a new function
    
    var add2000 = add(2000);
    
    add2000(10);
    // 2010

    General-purpose currying function

    function schonfinkelize(fn) {
    
        var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1);
    
        return function() {
    
            var new_args = slice.call(arguments), args = stored_args.concat(new_args);
    
            return fn.apply(null, args);
    
        };
    
    }
    
    // a normal function
    
    function add(x, y) {
    
        return x + y;
    
    }
    
    // curry a function to get a new function
    
    var newadd = schonfinkelize(add, 5);
    
    newadd(4);
    // 9
    
    // another option -- call the new function directly
    
    schonfinkelize(add, 6)(7);
    // 13
    
    // a normal function
    
    function add(a, b, c, d, e) {
    
        return a + b + c + d + e;
    
    }
    
    // works with any number of arguments
    
    schonfinkelize(add, 1, 2, 3)(5, 5);
    // 16
    
    // two-step currying
    
    var addOne = schonfinkelize(add, 1);
    
    addOne(10, 10, 10, 10);
    // 41
    
    var addSix = schonfinkelize(addOne, 2, 3);
    
    addSix(5, 5);
    // 16

    When to Use Currying

    When you find yourself calling the same function and passing mostly the same parameters, then the function is probably a good candidate for currying. You can create a new function dynamically by partially applying a set of arguments to your function. The new function will keep the repeated parameters stored (so you don’t have to pass them every time) and will use them to pre-fill the full list of arguments that the original function expects.

    References: 

    JavaScript Patterns - by Stoyan Stefanov (O`Reilly)

  • 相关阅读:
    请使用迭代查找一个list中最小和最大值,并返回一个tuple
    利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法
    软件测试中的43个功能测试点总结
    Linux下好用的简单实用命令
    小议堆栈
    使用mac的那些稀奇古怪的事
    探索TypeScript第一步之基础类型
    Markdown的基本使用方法
    React的生命周期
    React中的通讯组件
  • 原文地址:https://www.cnblogs.com/haokaibo/p/curry.html
Copyright © 2011-2022 走看看