微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我尝试使用 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

sum(1,2)(3) 运行时,我得到

sum(...) 不是函数

分别运行底部的 3 行时它可以正常工作, 但一起它会抛出那个错误

解决方法

您使用了两次 sum 变量来进行柯里化,这只会保存一组参数。

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

这可以解决您的问题:

TextBox

,

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

,

问题是您目前有一个 args 的单个实例,该实例在所有版本的装饰柯里化函数之间共享。这意味着一旦您获得足够的参数一次,任何进一步的柯里化调用都将直接转到 return fn(...args),因此再次执行将失败:

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

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

在第四次调用 sum(1,2) 时,args 数组包含的 [1,2]fn.length 更多,因此 sum(1,2) 将执行函数并返回 6。下一个 (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,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

您可以利用 curryDecorate 已经将 args 作为参数的事实,以避免此错误。如果柯里化调用不满足参数要求,您可以使用到目前为止的所有参数再次调用 curryDecorate。这样你就可以得到单独的函数对象,每个对象都有一个单独的部分填充的参数列表:

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,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; }

再向前迈出一步,如果 curryDecorate 无论如何都要用参数调用,执行或不执行函数的逻辑可以移到那里,事情会稍微简化:

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

const curryDecorate = (fn,...newArgs);
}

const add = (a,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; }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。