Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 15 题:实现 add(1)(2)(3) #21

Open
lgwebdream opened this issue Jun 19, 2020 · 20 comments
Open

第 15 题:实现 add(1)(2)(3) #21

lgwebdream opened this issue Jun 19, 2020 · 20 comments
Labels
JavaScript teach_tag 滴滴 company

Comments

@lgwebdream
Copy link
Owner

lgwebdream commented Jun 19, 2020

欢迎在下方发表您的优质见解

@lgwebdream lgwebdream added JavaScript teach_tag 滴滴 company labels Jun 19, 2020
@Genzhen
Copy link
Collaborator

Genzhen commented Jun 23, 2020

考点:函数柯里化

函数柯里化概念: 柯里化(Currying)是把接受多个参数的函数转变为接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术。

1)粗暴版

function add (a) {
	return function (b) {
		return function (c) {
		    return a + b + c;
		}
	}
}
console.log(add(1)(2)(3)); // 6

2)柯里化解决方案

  • 参数长度固定
const curry = (fn) =>
(judge = (...args) =>
    args.length === fn.length
    ? fn(...args)
    : (...arg) => judge(...args, ...arg));
const add = (a, b, c) => a + b + c;
const curryAdd = curry(add);
console.log(curryAdd(1)(2)(3)); // 6
console.log(curryAdd(1, 2)(3)); // 6
console.log(curryAdd(1)(2, 3)); // 6
  • 参数长度不固定
function add (...args) {
    //求和
    return args.reduce((a, b) => a + b)
}

function currying (fn) {
    let args = []
    return function temp (...newArgs) {
        if (newArgs.length) {
            args = [
                ...args,
                ...newArgs
            ]
            return temp
        } else {
            let val = fn.apply(this, args)
            args = [] //保证再次调用时清空
            return val
        }
    }
}

let addCurry = currying(add)
console.log(addCurry(1)(2)(3)(4, 5)())  //15
console.log(addCurry(1)(2)(3, 4, 5)())  //15
console.log(addCurry(1)(2, 3, 4, 5)())  //15

@H246802
Copy link

H246802 commented Jul 15, 2020

function currying(){
    let args = [...arguments]
    temp.getValue = ()=>{
        return args.reduce((a,b)=> a + b, 0)
    }
    function temp(...arg){
        if(arg.length){
            args = [
                ...args,
                ...arg
            ]
            return temp
        }
    }
    return temp
}

@123456zzz
Copy link

const add = (a: number, b: number, c: number) => a + b + c;

const adding = (...args: number[]) => args.reduce((pre, cur) => pre + cur, 0);

//参数确定
const curry = (fn: Function) => {
  let args = [];

  return function temp(...newArgs) {
    args.push(...newArgs);
    if (args.length === fn.length) {
      const val = fn.apply(this, args);
      args = [];
      return val;
    } else {
      return temp;
    }
  };
};

//参数不确定
const currying = (fn: Function) => {
  let args = [];

  return function temp(...newArgs) {
    if (newArgs.length) {
      args.push(...newArgs);
      return temp;
    } else {
      const val = fn.apply(this, args);
      args = [];
      return val;
    }
  };
};

const curryAdd = curry(add);
console.log(curryAdd(1)(2)(3)); // 6
console.log(curryAdd(1, 2)(3)); // 6
console.log(curryAdd(1)(2, 3)); // 6

let addCurry = currying(adding);
console.log(addCurry(1)(2)(3)(4, 5)()); //15
console.log(addCurry(1)(2)(3, 4, 5)()); //15
console.log(addCurry(1)(2, 3, 4, 5)()); //15

@yaooooooooo
Copy link

yaooooooooo commented Jul 20, 2020

function curring(fn,arr = []){
  var length = fn.length;
  return (...args) => {
   const currentArr = [...arr.push(args)]
   if(arr.length < length){
        return curring(fn,currentArr];
    } else {
         fn(...currentArr )
    }
  }
}

@Genzhen Genzhen closed this as completed Jul 20, 2020
@GolderBrother
Copy link

GolderBrother commented Jul 20, 2020

function currying(fn, args = []) {
    return function temp(...innerArgs) {
        if (innerArgs.length > 0) {
            // 收集后面传入的参数
            args = [...args, ...innerArgs];
            // 返回函数供后面可以继续调用
            return temp;
        } else {
            const val = fn.apply(this, args);
            // 清空参数数组,为了保证下次执行函数可以继续迭代
            args = [];
            return val;
        }
    }
}
// 求和函数
const add = (...args) => args.reduce((a, b) => a + b);
let addCurry = currying(add)
console.log(addCurry(1)(2)(3)(4, 5)())  //15
console.log(addCurry(1)(2)(3, 4, 5)())  //15
console.log(addCurry(1)(2, 3, 4, 5)())  //15

@JL003
Copy link

JL003 commented Jul 24, 2020

除了typeof为function 正常运算都没问题
function add(num) {
const add2 = (num2) => {
num = num + num2;
add2.toString = () => num;
return add2;
}
return add2;
}
add(1)(2)(3) + 5 // 11
add(1)(2)(3)(4) // ƒ 10

@Genzhen Genzhen reopened this Jul 29, 2020
@ABoyCDog
Copy link

有个疑问,就是参数长度不固定时,addCurry(1)(2)(3)(4, 5)(),最后的需要加函数执行的(),但是题目不是没有吗,也就是只要addCurry(1)(2)(3)(4, 5)这样

@huzedong2015
Copy link

function curry(fn, ...args) {
    if (args.length >= fn.length) {
        return fn(...args);
    }

    return (...args2) => curry(fn, ...args, ...args2);
}

function sum(a, b, c) {
    return a + b + c;
}

let add = curry(sum);

console.log(add(1)(2)(3));

@mapoio
Copy link

mapoio commented Oct 17, 2020

function add (...params) {
    let result = params.reduceRight((a, b) => a + b)
    const tmp = (...paramsInit) => {
        result = [...paramsInit, result].reduceRight((a, b) => a + b)
        return tmp
    }
    tmp.toString = () => `${result}`
    tmp.valueOf = () => result
    return tmp
}

可以这样实现
@ABoyCDog

@m7yue
Copy link

m7yue commented Feb 8, 2021

const curryAdd = (...args) => {
  const Add = (...args2) => {
    return curry(...args, ...args2)
  }
  Add.toString = () => args.reduce((t, v) => t+v);
  
  return Add
}

console.log(curryAdd(1)(2)(3,4))

@wjiantao
Copy link

function curry(fn, args) {
  var length = fn.length;
  args = args || [];
  return function () {
    newArgs = args.conct(Array.prototype.slice.call(arguments));
    return newArgs.length < length
      ? curry.call(this, fn, newArgs)
      : fn.apply(this, newArgs);
  };
}

function multiFn(a, b, c) {
  return a * b * c;
}

var multi = curry(multiFn);

console.log(multi(2)(3)(4));

@geekftz
Copy link

geekftz commented Jul 13, 2021

const sum = (arr) => {
return arr.reduce((pre, cur, index) => {
return pre + cur
}, 0)
}

function add() {
const outArgs = Array.from(arguments)
let res = sum(outArgs);

function newAdd() {
if (arguments.length > 0) {
const innerArgs = Array.from(arguments);
res += sum(innerArgs)
return newAdd
} else {
return res;
}
}

newAdd.valueOf = function () {
return res
}

newAdd.toString = function () {
return res + ''
}

return newAdd
}

var result = add(1, 2)(3)(4)(5); // 参数可能为多个的情况下

console.log(result());

@xcs-go
Copy link

xcs-go commented Jul 24, 2021

function curry(fn, args) {
    const { length } = fn;
    const params = args || [];
    return function() {
        const args = params.concat([].slice.call(arguments));
        if (args.length < length) {
            return curry.apply(this, fn, args); 
       } else {
           return fn.apply(this, args);
      }
   }
}

@Evllis
Copy link

Evllis commented Aug 11, 2021

const curryAdd = (...args) => {
  const Add = (...args2) => {
    return curry(...args, ...args2)
  }
  Add.toString = () => args.reduce((t, v) => t+v);
  
  return Add
}

console.log(curryAdd(1)(2)(3,4))

测一测吧,测好了再发出来。curry已经undefined了。

image

@1uckyneo
Copy link

const curry = (fn) => {
  const prevArgs = [];

  const rec = (...currArgs) => {
    prevArgs.push(...currArgs);
    
    if(fn.length - prevArgs.length <= 0) {
      return fn(...prevArgs);
    }
    
    return rec;
  }

  return rec;
}

const add = (a: number, b: number, c: number) => a + b + c;
const curryAdd = curry(add);

@zizxzy
Copy link

zizxzy commented Nov 2, 2021

函数的柯里化的应用

const curry = (fn, args) => {
  const length = fn.length;
  let _args = args || [];
  return function () {
    let argArray = _args.slice(0);
    for (let i = 0; i < arguments.length; i++) {
      argArray.push(arguments[i]);
    }
    if (argArray.length < length) {
      return curry(fn, argArray);
    } else {
      return fn.apply(this, argArray);
    }
  }
}
const add = curry(function (a, b, c) {
  return a + b + c;
})
console.log(add(1)(2)(3));

@ikozn
Copy link

ikozn commented Feb 26, 2022

const add = a => b => c => a + b + c

@wringY
Copy link

wringY commented Mar 28, 2022

function curry(fn) {
const length = fn.length
return function _curry(...args) {
if (args.length >= length) {
return fn.apply(this, args)
} else {
return _curry.bind(this, ...args)
}
}
}
// 测试
function add(x, y, z) {
return this.val + x + y + z
}
let fun1 = curry(add)
let obj = {
val: 10,
fun1
}
console.log(obj.fun1(1)(2)(3))

@chinbor
Copy link

chinbor commented Aug 2, 2023

function curry(...args1) {
  const fn = args1[0]
  const restArgs = args1.slice(1)

  function curried(...args2) {
    return curry.call(this, fn, ...[...restArgs, ...args2])
  }

  curried.toString = function() {
    return fn.call(this, ...restArgs)
  }

  return curried
}

function sum(...args) {
  let result = 0

  args.forEach(arg => {
    result += arg
  })

  return result
}

const add = curry(sum)

// toString 修改了但是不生效,需要自己利用 + 操作符进行转换
console.log(+add(1)(2)(3, 4, 5))

@Kisthanny
Copy link

暴力写法

function add(a) {
  return function (b) {
    return function (c) {
      return a + b + c;
    };
  };
}

console.log(add(1)(2)(3))

如果不限调用3次呢,比如add(1)(2)(3)(4)返回8

// 通过返回一个拥有获取值方法的函数
function add(x) {
  let sum = x;

  function innerAdd(y) {
    sum += y;
    return innerAdd;
  }

  innerAdd.getResult = function () {
    return sum;
  };

  return innerAdd;
}

console.log(add(1)(2)(3)(4).getResult()); // 输出 10
// 缺点:获取值时需要额外调用.getResult()

题目没说add(1)(2)(3)就是返回值了,有没有可能是类里的方法

class MyNumber {
  constructor(value) {
    this.value = value;
  }
  add(num) {
    this.value += num;
    return this.add.bind(this);
  }
}
const myNum = new MyNumber(0);
myNum.add(1)(2)(3);
console.log(myNum.value);

函数柯里化

// Function.length返回函数必传参数的长度
const curry = (fn) => {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn(...args);
    } else {
      return function (...nextArgs) {
        return curried(...args, ...nextArgs);
      };
    }
  };
};
const baseAdd = (a, b, c) => a + b + c;
const add = curry(baseAdd);
console.log(add(1)(2)(3)); // 6
console.log(add(1, 2)(3)); // 6
console.log(add(1)(2, 3)); // 6
console.log(add(1, 2, 3)); // 6
console.log(add(1)(2)); // 返回方法
try {
  console.log(add(1)(2)(3)(4)); // 报错
} catch (error) {
  console.error(error);
}
// 缺点,baseAdd长度写死,比暴力好在修改baseAdd更简单

不限长度的函数柯里化

const infiniteCurry = (fn) => {
  let lastArgsLength = 0;
  return function curried(...args) {
    if (args.length === lastArgsLength) {
      return fn(...args);
    } else {
      lastArgsLength = args.length;
      return function (...nextArgs) {
        return curried(...args, ...nextArgs);
      };
    }
  };
};
const infiniteAdd = (...args) => {
  return Array.from(args).reduce((a, b) => a + b);
};
const add = infiniteCurry(infiniteAdd);
console.log(add(1)(2)());
console.log(add(1)(2)(3)());
console.log(add(1)(2)(3)(4)());
console.log(add(1, 2, 3)(4, 5)());
console.log(add(1, 2, 3, 4, 5, 6)());
// 缺点:获取值时要()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScript teach_tag 滴滴 company
Projects
None yet
Development

No branches or pull requests