【问题标题】:How to write point-free functional JS using Ramda如何使用 Ramda 编写无点函数式 JS
【发布时间】:2018-11-12 20:35:29
【问题描述】:

我有一个对象数组

const myNumbers = [
  {
   top: 10,
   bottom: 5,
   rate: 5
  },
  {
   top: 9,
   bottom: 4,
   rate: 3
  },
];

我想在对它们进行任何操作之前运行一些使数字可用的函数;

const addTen = r.add(10);
const double = r.multiply(2);

还有一个接受数字并做一些数学运算的函数:

const process = (top, bottom, rate) => r.multiply(r.subtract(bottom, top), rate)

所以我的最终函数看起来像

muNymbers.map(({ top, bottom, rate }) =>
  process(addTen(top), double(bottom), rate)
);

只要看看这段代码,你就会发现这两个函数已经变得非常嵌套并且不是特别清晰。我的真正问题又稍微复杂了一点,我正在努力寻找在为不同的操作选择不同的值时如何使这一点变得毫无意义。

【问题讨论】:

    标签: javascript ramda.js pointfree


    【解决方案1】:

    这是一种无点方法。您正在寻找的主要功能是pipeevolveconverge。我不确定这是否是最好的方式,这只是我能想到的最好的方式:

    const { add, converge, evolve, map, multiply, pipe, prop, subtract } = R;
    
    const myNumbers = [
        { top: 10, bottom: 5, rate: 5 },
        { top: 9, bottom: 4, rate: 3 },
    ];
    
    const process = pipe(
    
        evolve({
            top: add(10),
            bottom: multiply(2),
        }),
    
        converge(multiply, [
    
            converge(subtract, [
                prop('bottom'),
                prop('top'),
            ]),
    
            prop('rate'),
        ]),
    );
    
    console.log(map(process, myNumbers));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

    【讨论】:

    • 太棒了!这正是我一直在寻找的东西,我只是想不通如何让它发挥作用。用compose尝试过prop,但无法以默契的方式表达自己。
    • 是的,我一开始也是这么想的。真的是converge 在这里起到了作用,允许您将多个函数应用于“并行”中的相同输入。很高兴为您提供帮助!
    【解决方案2】:

    如果这是编写无点代码的练习,那么像@JeffreyWesterkamp 这样的解决方案就可以了。

    不过,对于生产代码,任何无点解决方案都将比这个简单版本的可读性很多

    const process = ({top, bottom, rate}) => ((2 * bottom) - (10 + top)) * rate;
    
    const myNumbers = [
        { top: 10, bottom: 5, rate: 5 },
        { top: 9, bottom: 4, rate: 3 },
    ];
    
    console.log(R.map(process, myNumbers));
    <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

    关键是不要盲目崇拜。它是一种有时使代码更易于阅读、更易于理解的工具。但是不这样做就不值得使用了。

    不要误会我的意思。我是无点代码的忠实粉丝,Ramda(免责声明:我是它的作者之一)有一些有用的工具可以帮助您编写它。但是 Ramda 与其他代码一起工作得很好。所以要明智地使用它。


    另外一点(咳咳):Ramda 提供了两个相当不寻常的函数,useWithconverge,以便更轻松地编写无点代码。但是converge 通常可以用更标准的lift 代替。它不能总是被替换,因为它有一些 lift 不提供的处理可变参数函数的特性,但是当你可以使用 lift 时,我建议你这样做。例如,而不是

    converge(subtract, [prop('bottom'), prop('top')])
    

    你可以写

    lift(subtract)(prop('bottom'), prop('top'))
    

    据我所知,useWith 没有标准替代品。但我会尽可能将converge 替换为lift

    【讨论】:

    • 感谢@scott-sauyet 的回答,您对可读性有很强的看法。在生产代码中,我可能会写一些功能较少的东西,并且更容易被团队维护;但我正在做一个个人项目,想加深对无点代码的理解。与 Ramda 一起玩似乎是一个不错的起点。
    猜你喜欢
    • 1970-01-01
    • 2019-08-19
    • 2017-02-22
    • 1970-01-01
    • 2017-10-07
    • 2016-07-11
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多