V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
vision1900
V2EX  ›  JavaScript

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

  •  
  •   vision1900 · 2020-11-24 16:09:02 +08:00 · 2709 次点击
    这是一个创建于 1466 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    3. 你这个 for 循环不知道在干什么
    ksedz
        8
    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
        9
    ksedz  
       2020-11-24 19:59:01 +08:00
    vision1900
        10
    vision1900  
    OP
       2020-11-25 10:29:55 +08:00
    @ksedz 谢谢,我再研究下
    pwn
        11
    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
        12
    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
        13
    pwn  
       2020-11-25 11:06:02 +08:00
    罢了罢了,给个链接 https://paste.ubuntu.com/p/q49C9WcYJZ/
    pwn
        14
    pwn  
       2020-11-25 20:20:36 +08:00
    写错了,不好意思,再来: https://paste.ubuntu.com/p/hr2J2dgzp2/
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4687 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:01 · PVG 18:01 · LAX 02:01 · JFK 05:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.