这样的柯里化实现为什么不 Work?

2020-11-24 16:09:02 +08:00
 vision1900

下午尝试自己实现柯里化,写出了如下代码:

这是代码截图: http://realrz.com/curry_not_working.png

function curry(f, params_count) {
  if ([0, 1].includes(params_count)) return f;
  const params = [];
  let result_fuction = f(...params);
  for (let i = 0; i < params_count; i++) {
    result_function = function (val) {
      params.push(val);
      return result_function;
    };
  }
  return result_function;
}

function add1(a, b) { return a + b }
function add2(a, b, c) { return a + b + c }

const curriedAdd1 = curry(add1, 2);
const curriedAdd2 = curry(add2, 3);

curriedAdd1(1)(2); // 没有得到 3
curriedAdd2(1)(2)(3); // 没有得到 6
2495 次点击
所在节点    JavaScript
14 条回复
noe132
2020-11-24 16:27:43 +08:00
你这连递归都没有看见。。。感觉差的有点远啊
建议参考 https://stackoverflow.com/questions/27996544/how-to-correctly-curry-a-function-in-javascript
noe132
2020-11-24 16:29:58 +08:00
而且中间的 for 循环等于在做无用功。运行 n 次和运行一次,得到的 result_function 都是一样的东西
linoder
2020-11-24 16:30:53 +08:00
因为 You 写的 CASE 有 BUG
vision1900
2020-11-24 16:39:49 +08:00
@noe132 我的意图是把参数个数 map 到函数的阶,递归 + Function.prototype.apply 是可以实现: https://javascript.info/currying-partials#advanced-curry-implementation
但我的问题是手动提阶为什么不行
linvaux
2020-11-24 16:39:55 +08:00
@linoder 说的很 right
dantegg
2020-11-24 16:43:43 +08:00
@linoder you 的回复 very 酷
noe132
2020-11-24 16:50:01 +08:00
1. 你 curry 出来的函数共享一个闭包
a = curry(3, fn)

b = a(1)
c = a(1)

b 和 c 调用会相互影响,得到的就不是纯函数

2. 你的判断至少要放到 result_function 里面才有用。你每次执行只是 push 了一个值然后又返回 result_function 本身,你执行 1w 次也是这样,还会造成内存泄漏

3. 你这个 for 循环不知道在干什么
ksedz
2020-11-24 19:56:57 +08:00
function curry(f, params_count) {
if ([0, 1].includes(params_count)) return f;
let result_function = f;
for (let i = 1; i < params_count; i++) {
const last_result_function = result_function
result_function = function(...params) {
return function(...params2) {
params2 = params2.concat(params)
return last_result_function(...params2)
}
}
}
return result_function;
}

function add1(a, b) { return a + b }
function add2(a, b, c) { return a + b + c }

const curriedAdd1 = curry(add1, 2);
const curriedAdd2 = curry(add2, 3);

console.log(curriedAdd1(1)(2)); // 3
console.log(curriedAdd1(3)(2)); // 5
const t = curriedAdd1(1)
console.log(t(2)); // 3
console.log(t(3)); // 4
console.log(curriedAdd2(1)(2)(3)); // 6
ksedz
2020-11-24 19:59:01 +08:00
vision1900
2020-11-25 10:29:55 +08:00
@ksedz 谢谢,我再研究下
pwn
2020-11-25 11:03:18 +08:00
试着写了一下
----
function curry(f, params_count) {
let count = params_count;
let params = [];
let closure = function(...param) {
params = params.concat(param)
if (params.length >= count) {
let sum = 0;
for (let i = 0; i < count; i++)
sum += params[i];
params = params.slice(count)
return sum;
} else {
return closure
}
}
return closure;
}
pwn
2020-11-25 11:04:29 +08:00
为什么前面空格会自动去掉。。试试这样
// function curry(f, params_count) {
// let count = params_count;
// let params = [];
// let closure = function(...param) {
// params = params.concat(param)
// if (params.length >= count) {
// let sum = 0;
// for (let i = 0; i < count; i++)
// sum += params[i];
// params = params.slice(count)
// return sum;
// } else {
// return closure
// }
// }
// return closure;
// }
pwn
2020-11-25 11:06:02 +08:00
罢了罢了,给个链接 https://paste.ubuntu.com/p/q49C9WcYJZ/
pwn
2020-11-25 20:20:36 +08:00
写错了,不好意思,再来: https://paste.ubuntu.com/p/hr2J2dgzp2/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/728757

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX