在 Ramda 管道中使用相同的第一个参数
Using the same first argument in a Ramda pipe
是否可以在Ramda中编写以下函数?
(a, b) => R.pipe(func1(a), func2(a))(b)
目的是将参数 a
传递给 pipe
中的所有函数。
我最初的想法如下:
R.pipe(R.juxt([func1, func2]), R.apply(R.pipe))
但这给出了 TypeError: Cannot read property 'length' of undefined
.
您必须创建所有函数的柯里化版本,然后使用 a
调用每个函数的柯里化版本,最后在 R.pipe
或 [=21= 中使用 b
]
假设需要a
作为第一个参数的函数是f,g,h
(按照特定顺序)那么我们要实现以下表达式
h(a, g(a, f(a, b)))
首先让我们创建一个柯里化函数,它接收两个参数,一个值 v
和一个函数 fn
,当这个函数接收到所有必需的参数时,它将简单地 return fn(v)
const rev = R.curry((v, fn) => fn(v))
接下来我们可以使用 R.map
和 R.curry
创建函数的柯里化版本
// note the reversed order of the functions
// I'll use R.compose instead of R.pipe
let curriedVersion = R.map(R.curry, [h,g,f])
但是我们还需要使用 a
作为柯里化函数的第一个参数,我们可以使用 R.map
调用每个带有 a
的柯里化函数,但是我们将使用我们的特殊函数函数 rev
const curriedVersion = R.map(R.compose(rev(a), R.curry), [h,g,f])
最后让我们将这个柯里化函数数组与 R.compose
和 b
一起使用
const result = R.compose.apply(undefined, curriedVersion)(b)
一个衬里(对于特定顺序的函数 f,g,h
):
const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [h,g,f]))(b)
const add = (a, b) => a + b
const sub = (a, b) => a - b
const mul = (a, b) => a * b
const rev = R.curry((v, fn) => fn(v))
const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [mul,sub,add]))(b)
// mul(2, sub(2, add(2, 3)))
// mul(2, sub(2, 5))
// mul(2, -3)
// -6
console.log(solver(2, 3))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js"></script>
使用 S.pipe
更容易表达,因为它需要 数组 函数来组合。
一种选择是使用 R.ap
:
> S.pipe(R.ap([S.add, S.mult, S.add], [3]), 10)
42
另一种选择是使用 R.map
with S.T
,画眉组合器:
> S.pipe(R.map(S.T(3), [S.add, S.mult, S.add]), 10)
42
然后您可以将其中一个包装在 lambda 中以创建二进制函数:
const f = (a, b) => S.pipe(R.ap([S.add, S.mult, S.add], [a]), b);
f(3, 10); // add(3)(mult(3)(add(3)(10)))
// => 42
是否可以在Ramda中编写以下函数?
(a, b) => R.pipe(func1(a), func2(a))(b)
目的是将参数 a
传递给 pipe
中的所有函数。
我最初的想法如下:
R.pipe(R.juxt([func1, func2]), R.apply(R.pipe))
但这给出了 TypeError: Cannot read property 'length' of undefined
.
您必须创建所有函数的柯里化版本,然后使用 a
调用每个函数的柯里化版本,最后在 R.pipe
或 [=21= 中使用 b
]
假设需要a
作为第一个参数的函数是f,g,h
(按照特定顺序)那么我们要实现以下表达式
h(a, g(a, f(a, b)))
首先让我们创建一个柯里化函数,它接收两个参数,一个值 v
和一个函数 fn
,当这个函数接收到所有必需的参数时,它将简单地 return fn(v)
const rev = R.curry((v, fn) => fn(v))
接下来我们可以使用 R.map
和 R.curry
// note the reversed order of the functions
// I'll use R.compose instead of R.pipe
let curriedVersion = R.map(R.curry, [h,g,f])
但是我们还需要使用 a
作为柯里化函数的第一个参数,我们可以使用 R.map
调用每个带有 a
的柯里化函数,但是我们将使用我们的特殊函数函数 rev
const curriedVersion = R.map(R.compose(rev(a), R.curry), [h,g,f])
最后让我们将这个柯里化函数数组与 R.compose
和 b
const result = R.compose.apply(undefined, curriedVersion)(b)
一个衬里(对于特定顺序的函数 f,g,h
):
const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [h,g,f]))(b)
const add = (a, b) => a + b
const sub = (a, b) => a - b
const mul = (a, b) => a * b
const rev = R.curry((v, fn) => fn(v))
const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [mul,sub,add]))(b)
// mul(2, sub(2, add(2, 3)))
// mul(2, sub(2, 5))
// mul(2, -3)
// -6
console.log(solver(2, 3))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js"></script>
使用 S.pipe
更容易表达,因为它需要 数组 函数来组合。
一种选择是使用 R.ap
:
> S.pipe(R.ap([S.add, S.mult, S.add], [3]), 10)
42
另一种选择是使用 R.map
with S.T
,画眉组合器:
> S.pipe(R.map(S.T(3), [S.add, S.mult, S.add]), 10)
42
然后您可以将其中一个包装在 lambda 中以创建二进制函数:
const f = (a, b) => S.pipe(R.ap([S.add, S.mult, S.add], [a]), b);
f(3, 10); // add(3)(mult(3)(add(3)(10)))
// => 42