N-ZOO / everycode

前端每日一练
163 stars 18 forks source link

[js] 实现一个自动化柯里化方法 #24

Open VaJoy opened 6 years ago

VaJoy commented 6 years ago
//TODO - 实现一个自动化柯里化方法 curry

const curriedSum = curry((x, y, z) => x + y + z);

curriedSum(1, 2)(3);   // 6
curriedSum(1, 2)(3);   // 6
curriedSum(1)(2)(3);   // 6
curriedSum(1, 2, 3);   // 6

思考下如何实现这个 curry 函数,不建议参考别人代码

zpdf commented 6 years ago

function curry (fn){ const length = fn.length; return function curriedFn(...args){ if(args.length>=length){ return fn(...args) }else{ return curriedFn.bind(null,...args) } } }

VaJoy commented 6 years ago

贴个coco的解法思路,挺抖机灵的:

function add () {
    console.log('进入add');
    var args = Array.prototype.slice.call(arguments);

    var fn = function () {
        var arg_fn = Array.prototype.slice.call(arguments);
        console.log('调用fn');
        return add.apply(null, args.concat(arg_fn));
    }

    fn.valueOf = function () {
        console.log('调用valueOf');
        return args.reduce(function(a, b) {
            return a + b;
        })
    }

    return fn;
}
Jiasm commented 6 years ago

之前写过的一个:

/**
 * 柯里化的一种实现方式
 */

function currying (...arg) {
  val = arg.reduce((cur, old) => cur + old, 0)
  return Object.assign(currying.bind(this, val), {
    valueOf () {
      return val
    },
    toString () {
      return val
    },
    toLocaleString () {
      return val
    }
  })
}
var a = currying(1)(2)

// 因为console.log实现的问题。。所以必须在前边添加一个+来确保能够得到正确的输出
console.log(+a, +a(4), +a(5, 6))

或者一个较为通用的实现方法:https://github.com/Jiasm/notebook/blob/master/currying.js

uinz commented 6 years ago
function curry(fn) {
    const _inner = (...args1) => args1.length < fn.length
        ? (...args2) => _inner(...args1, ...args2)
        : fn(...args1)

    return _inner
}

const curriedSum = curry((x, y, z) => x + y + z);