Ramda - R.both 带有咖喱谓词
Ramda - R.both with curried predicates
我的目标是 link 两个谓词在 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
真的很困惑 - 我在这里错过了什么?
我认为 R.both 默认没有柯里化。如果你这样做 R.curryN(2, R.both(a, b))
那么它会按预期工作。查看此 REPL 以查看示例。
根据 both
的 Ramda 来源
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);
});
如果第一个参数是函数,则不会返回柯里化函数。
我认为是 Ramda 的 both
is slightly out of sync with the majority of the library (disclaimer: I'm one of the Ramda authors.) The result of both
probably should be curried to the maximum length of its arguments, as happens with its close affiliate 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)
一样。这两个都是 truth-y,所以 &&
returns 第二个。
这应该可以解释发生了什么。
我认为 Ramda 的 both
功能应该更新。但是,正如其他人所建议的那样,您可以通过柯里化 both
.
的结果来完成这项工作
还有一点:你可以用 Ramda 的 eqProps
:
更简单地写 isXEqual
/isYEqual
const isXEqual = R.eqProps('x')
const isYEqual = R.eqProps('y')
我的目标是 link 两个谓词在 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
真的很困惑 - 我在这里错过了什么?
我认为 R.both 默认没有柯里化。如果你这样做 R.curryN(2, R.both(a, b))
那么它会按预期工作。查看此 REPL 以查看示例。
根据 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);
});
如果第一个参数是函数,则不会返回柯里化函数。
我认为是 Ramda 的 both
is slightly out of sync with the majority of the library (disclaimer: I'm one of the Ramda authors.) The result of both
probably should be curried to the maximum length of its arguments, as happens with its close affiliate 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)
一样。这两个都是 truth-y,所以 &&
returns 第二个。
这应该可以解释发生了什么。
我认为 Ramda 的 both
功能应该更新。但是,正如其他人所建议的那样,您可以通过柯里化 both
.
还有一点:你可以用 Ramda 的 eqProps
:
isXEqual
/isYEqual
const isXEqual = R.eqProps('x')
const isYEqual = R.eqProps('y')