【问题标题】:Ramda - R.both with curried predicatesRamda - 带有咖喱谓词的 R.both
【发布时间】:2018-01-30 22:16:53
【问题描述】:

我的目标是链接两个在 R.both 中采用相同两个参数的谓词,以便我可以独立传递参数 - 即 curried。

这是我整理的 repl 实现:

const isXEqual = (obj1, obj2) => R.equals(obj1.x, obj2.x);
const isYEqual = (obj1, obj2) => R.equals(obj1.y, obj2.y);

const a = R.curry(isXEqual);
const b = R.curry(isYEqual);

const isBoth_Curried = R.both(a, b);

const obj1 =  {"x": 6, "y": 5};
const obj2 =  {"x": 6, "y": 5};
const obj3 =  {"x": 5, "y": 5};

isBoth_Curried(obj1, obj2); //==> true
isBoth_Curried(obj1, obj3); //==> false

isBoth_Curried(obj1)(obj2); //==> true

但是: isBoth_Curried(obj1)(obj3); //==> true

真的很困惑 - 我在这里错过了什么?

【问题讨论】:

    标签: javascript functional-programming ramda.js


    【解决方案1】:

    我认为 Ramda 的 both 与图书馆的大部分内容略有不同步(免责声明:我是 Ramda 的作者之一。)both 的结果可能应该被咖喱到它的论点的最大长度,就像它的密切附属机构allPass一样。所以这应该会按您预期的方式工作。

    但是,正如您所建议的,我认为您缺少一些基本的东西。内部函数被柯里化并不重要。它们只会被调用一次,带有所有参数:

    R.both(a, b)(obj1)(obj3)                 //~> [1]
    
    (function () {
      return a.apply(this, arguments) && a.apply(this, arguments);
    })(obj1)(obj3)                           //~> [2]
    
    (isXEqual(obj1) && isYEqual(obj1))(obj3) //~> [3]
    
    (isYEqual(obj))(obj3)                    //~> [4]
    
    R.equals(obj1.y, obj2.y)                 //~> [5]
    
    R.equals(5, 5)                           //=> [6]
    
    true
    

    最有可能绊倒你的步骤是 [3],(isXEqual(obj1) && isYEqual(obj1))(obj3) ~> (isYEqual(obj))(obj3)。关键是isXEqual(obj1) 是一个函数,因为你的currying,就像isYEqual(obj1) 一样。这两个都是真的,所以&& 返回第二个。

    这应该可以解释发生了什么。

    我确实认为 Ramda 的 both 函数应该更新。但是,正如其他人所建议的那样,您可以通过对both 的结果进行柯里化来完成这项工作。


    还有一点:isXEqual/isYEqual 可以用 Ramda 的eqProps 写得更简单:

    const isXEqual = R.eqProps('x')
    const isYEqual = R.eqProps('y')
    

    【讨论】:

    • 宾果游戏!是的,第 3 步让我失望了。感谢您详细说明
    【解决方案2】:

    我认为默认情况下 R.both 不是咖喱。如果您这样做R.curryN(2, R.both(a, b)),那么它会按预期工作。查看此REPL 以查看示例。

    【讨论】:

    • 好的,我知道它有效,但我真的不明白为什么。两个不同的问题:1)为什么不柯里化ab 工作?我觉得我没有理解一些基本的东西。 2) 正在玩您的 REPL,发现 R.curry(R.both(a,b)) 不起作用。为什么我们需要用R.curryN进行约束?
    【解决方案3】:

    根据 Ramda 的来源both

    var both = _curry2(function both(f, g) {
      return _isFunction(f) ?
        function _both() {
          return f.apply(this, arguments) && g.apply(this, arguments);
        } :
        lift(and)(f, g);
    });
    

    如果第一个参数是函数,则不会返回柯里化函数。

    【讨论】:

    • 是的,但这就是为什么我使用了 f (isXEqual) 和 g (isYEqual)。这是否应该返回一个 fg 来“等待”提供 2 个参数?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 2018-02-02
    • 1970-01-01
    相关资源
    最近更新 更多