Ramda - R.both与咖喱的谓词

时间:2018-01-30 01:52:45

标签: javascript functional-programming ramda.js

我的目标是链接两个谓词,这些谓词在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

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

3 个答案:

答案 0 :(得分:3)

我认为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的结果来完成这项工作。

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

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

答案 1 :(得分:1)

我认为R.both默认不是curry。如果你做R.curryN(2, R.both(a, b))那么它就像预期的那样工作。请查看此REPL以查看示例。

答案 2 :(得分:1)

根据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);
});

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