简体   繁体   English

我如何正确地咖喱这个功能?

[英]How do I curry this function correctly?

I tried to curry a function add using curryDecorate我尝试使用curryDecorate add curryDecorate

 const curryDecorate = (fn, ...args) => { const curried = (...newArgs) => { args = args.concat(newArgs) if (args.length < fn.length) { return curried } return fn(...args) } return curried } const add = (a, b, c) => a + b + c const sum = curryDecorate(add) console.log(sum(1)(2)(3)) // 6 console.log(sum(1, 2)(3)) // 6 console.log(sum(1)(2, 3)) // 6

When sum(1, 2)(3) is run, I getsum(1, 2)(3)运行时,我得到

sum(...) is not a function sum(...) 不是函数

It works correctly when running the 3 lines at the bottom separately, but together it throws that error.分别运行底部的 3 行时,它可以正常工作,但一起运行会引发该错误。

You're using the sum variable twice to curry, which only saves one group of arguments.您使用sum变量两次进行咖喱运算,这只会保存一组参数。

sum(1)(2)(3) // args: 1, 2, 3
sum(1, 2) // persists, so args: 1, 2, 3, 1, 2

This solves your problem:这可以解决您的问题:

 const curryDecorate = (fn, ...args) => { let pass=[...args]; const curried = (...newArgs) => { pass= pass.concat(newArgs) if (pass.length < fn.length) { return curried } const val = fn(...pass); pass=[...args] return val; } return curried } const add = (a, b, c) => a + b + c const sum = curryDecorate(add) console.log(sum(1)(2)(3)) // 6 console.log(sum(1, 2)(3)) // 6 console.log(sum(1)(2, 3)) // 6

 const curryDecorate = (fn, ...args) => { const curried = (...newArgs) => { args = args.concat(newArgs) console.log('fn len', fn.length, args.length, args.length < fn.length) if (args.length < fn.length){ return curried } const currArgs = [...args] args = [] return fn(...currArgs) } return curried } const add = (a, b, c) => console.log(a + b + c) const sum = curryDecorate(add) sum(1)(2)(3) sum(1)(2)(3) sum(1)(2)(3) sum(1)(2)(3) sum(1)(2)(3) // 6

The problem is that you currently have one single instance of args that is shared between all versions of the decorated curried function.问题是您目前只有一个args实例,在所有版本的装饰咖喱函数之间共享。 This means that once you acquire enough arguments once any further curried calls will just go directly to return fn(...args) and thus executing again will fail:这意味着一旦您获得足够的参数,一旦任何进一步的柯里化调用将直接return fn(...args) ,因此再次执行将失败:

             console.log(sum (1) (2) (3))
//                           ^^^ ^^^ ^^^
//                            |   |   |
//args = [1] -----------------+   |   |
//args = [1, 2] ------------------+   |
//args = [1, 2, 3] -------------------+

             console.log(sum (1, 2) (3))
//                           ^^^^^^
//                             |
//args = [1, 2, 3, 1, 2] ------+ 

On the fourth call sum(1, 2) the args array contains [1, 2, 3, 1, 2] which is more than fn.length , therefore sum(1, 2) will execute the function and return 6 .在第四呼叫sum(1, 2)args数组包含[1, 2, 3, 1, 2]这是fn.length ,因此sum(1, 2)将执行功能,并返回6 The next (3) will attempt to execute the number as a function and fail:下一个(3)将尝试将数字作为函数执行并失败:

 const curryDecorate = (fn, ...args) => { const curried = (...newArgs) => { args = args.concat(newArgs) if (args.length < fn.length) { return curried } return fn(...args) } return curried } const add = (a, b, c) => a + b + c const sum = curryDecorate(add) console.log(sum(1)(2)(3)) // 6 const result = sum(1, 2); console.log(result) // 6 console.log(result(3)) // error

You can take advantage of the fact that curryDecorate already takes args as a parameter, in order to avoid this error.您可以利用curryDecorate已经将args作为参数的事实,以避免此错误。 If a curried call does not fulfil the argument requirements, you can call curryDecorate again with all arguments so far.如果curryDecorate调用curryDecorate参数要求,您可以使用到目前为止的所有参数再次调用curryDecorate That way you get separate function objects each with with a separate partially filled argument list:这样你就可以得到单独的函数对象,每个对象都有一个单独的部分填充的参数列表:

 const curryDecorate = (fn, ...args) => { const curried = (...newArgs) => { //collect all into newArgs newArgs = args.concat(newArgs) if (newArgs.length < fn.length) { //call curryDecorate with arguments so far return curryDecorate(fn, ...newArgs) } //execute with all collected args return fn(...newArgs) } return curried } const add = (a, b, c) => a + b + c const sum = curryDecorate(add) console.log(sum(1)(2)(3)) // 6 console.log(sum(1, 2)(3)) // 6 console.log(sum(1)(2, 3)) // 6 console.log("-----"); const sum1 = sum(1); const sum14 = sum1(4); const sum15 = sum1(5); const sum144 = sum14(4); const sum145 = sum14(5); const sum155 = sum15(5); const sum156 = sum15(6); console.log(sum144); console.log(sum145); console.log(sum155); console.log(sum156);
 .as-console-wrapper { max-height: 100% !important; }

Taking another step forward, if curryDecorate is going to be called with the arguments anyway, the logic to execute the function or not can be moved there and things are simplified a bit:再向前迈出一步,如果要使用参数调用curryDecorate ,则可以将执行或不执行函数的逻辑移到那里,并且稍微简化一下:

const curryDecorate = (fn, ...args) => {
  if (args.length >= fn.length)
    return fn(...args);
    
  return (...newArgs) =>
    curryDecorate(fn, ...args, ...newArgs);
}

 const curryDecorate = (fn, ...args) => { if (args.length >= fn.length) return fn(...args); return (...newArgs) => curryDecorate(fn, ...args, ...newArgs); } const add = (a, b, c) => a + b + c const sum = curryDecorate(add) console.log(sum(1)(2)(3)) // 6 console.log(sum(1, 2)(3)) // 6 console.log(sum(1)(2, 3)) // 6 console.log("-----"); const sum1 = sum(1); const sum14 = sum1(4); const sum15 = sum1(5); const sum144 = sum14(4); const sum145 = sum14(5); const sum155 = sum15(5); const sum156 = sum15(6); console.log(sum144); console.log(sum145); console.log(sum155); console.log(sum156);
 .as-console-wrapper { max-height: 100% !important; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM