Ramda 转换为自由点风格
Ramda Converting to Free-Point Style
我还没有真正找到适合这类事情的好资源。如果有人问这个问题,请提前道歉,虽然我找不到答案(可能是因为不知道如何搜索。
我有这个功能。它类似于 R.prepend
/R.append
,但它会将一个值推入列表的中间。
const insertMiddle = (val, arr) =>
R.insert(Math.floor(arr.length/2), val, arr);
我刚刚在学习函数式编程,所以我正在编写一个尽可能自由点风格的程序。即使这会降低可读性,我还是希望看到它完成。动脑筋开始功能性思考,看看如何以这种方式解决问题。
这是我所做的:
const halfLength = R.compose(
Math.floor,
R.divide(R.__, 2),
R.prop('length')
);
// ----
const insertMiddle = (val, arr) =>
R.insert(halfLength(arr), val, arr);
// ---- OR
const insertMiddle = (val, arr) =>
R.insert(halfLength(arr), val, R.identity(arr));
当然这还不是免费的
表面上这是下一步:
const insertMiddle = (val, arr) =>
R.insert(R.__, val)(halfLength(arr), R.identity(arr));
现在,如果我能让 (halfLength(arr), R.identity(arr))
成为无点数,我将得到一个只需要 val
的函数。
我这样做正确吗?接下来会发生什么?
如何:
x => foo(bar(x), x)
或
x => foo(bar(x),baz(x))
免费获得积分?
用两个函数调用的 R.chain - chain(f, g)(x) 等价于 f(g(x), x)。如果改变 R.insert (value & array) 的最后两个参数的顺序,我们可以用它来创建 insertMiddle
:
const { compose, divide, __, prop, curry, chain, insert } = R
const halfLength = compose(
Math.floor,
divide(__, 2),
prop('length')
)
const flippedInsert = curry((idx, val, arr) => insert(idx, arr, val))
const insertMiddle = chain(flippedInsert, halfLength)
const arr = [1, 2, 3, 4]
const result = insertMiddle(arr)('*')
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>
Ramda 确实提供了一些工具来简化无积分代码的编写。如果你只是四处闲逛,想看看它们是如何工作的,我们可以用它们做各种各样的事情。但我要重申,目标应该是可理解的代码。当它有助于提高可读性时使用无点;没有的时候跳过它。
有一些专门为此设计的 Ramda 函数。 (免责声明:我是 Ramda 的作者。)useWith
, converge
, and nthArg
在其中很突出。
我们可以使用 converge
和 nthArg
让它工作:
const {compose, divide, __, prop, converge, insert, pipe, nthArg} = R
const halfLength = compose (
Math .floor,
divide (__, 2),
prop ('length')
)
const insertMiddle = converge (insert, [pipe (nthArg (1), halfLength), nthArg (0), nthArg (1)])
console .log (insertMiddle (42, [1, 2, 3, 4, 5, 6]))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
我们甚至可以全力以赴并内联 halfLength
const insertMiddle = converge (insert, [
pipe (nthArg (1), prop ('length'), divide (__, 2), Math .floor),
nthArg (0),
nthArg (1)
])
同样,作为一个学习练习,这很好。但我发现其中任何一个都比一个简单的函数可读性差很多,只使用了一点 Ramda:
const insertMiddle = (x, xs) =>
insert ((xs .length >> 1), x, xs)
或普通版本:
const insertMiddle = (x, xs, mid = xs .length >> 1) =>
[... xs .slice (0, mid), x, ... xs .slice (mid)]
我还没有真正找到适合这类事情的好资源。如果有人问这个问题,请提前道歉,虽然我找不到答案(可能是因为不知道如何搜索。
我有这个功能。它类似于 R.prepend
/R.append
,但它会将一个值推入列表的中间。
const insertMiddle = (val, arr) =>
R.insert(Math.floor(arr.length/2), val, arr);
我刚刚在学习函数式编程,所以我正在编写一个尽可能自由点风格的程序。即使这会降低可读性,我还是希望看到它完成。动脑筋开始功能性思考,看看如何以这种方式解决问题。
这是我所做的:
const halfLength = R.compose(
Math.floor,
R.divide(R.__, 2),
R.prop('length')
);
// ----
const insertMiddle = (val, arr) =>
R.insert(halfLength(arr), val, arr);
// ---- OR
const insertMiddle = (val, arr) =>
R.insert(halfLength(arr), val, R.identity(arr));
当然这还不是免费的
表面上这是下一步:
const insertMiddle = (val, arr) =>
R.insert(R.__, val)(halfLength(arr), R.identity(arr));
现在,如果我能让 (halfLength(arr), R.identity(arr))
成为无点数,我将得到一个只需要 val
的函数。
我这样做正确吗?接下来会发生什么?
如何:
x => foo(bar(x), x)
或x => foo(bar(x),baz(x))
免费获得积分?
用两个函数调用的 R.chain - chain(f, g)(x) 等价于 f(g(x), x)。如果改变 R.insert (value & array) 的最后两个参数的顺序,我们可以用它来创建 insertMiddle
:
const { compose, divide, __, prop, curry, chain, insert } = R
const halfLength = compose(
Math.floor,
divide(__, 2),
prop('length')
)
const flippedInsert = curry((idx, val, arr) => insert(idx, arr, val))
const insertMiddle = chain(flippedInsert, halfLength)
const arr = [1, 2, 3, 4]
const result = insertMiddle(arr)('*')
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>
Ramda 确实提供了一些工具来简化无积分代码的编写。如果你只是四处闲逛,想看看它们是如何工作的,我们可以用它们做各种各样的事情。但我要重申,目标应该是可理解的代码。当它有助于提高可读性时使用无点;没有的时候跳过它。
有一些专门为此设计的 Ramda 函数。 (免责声明:我是 Ramda 的作者。)useWith
, converge
, and nthArg
在其中很突出。
我们可以使用 converge
和 nthArg
让它工作:
const {compose, divide, __, prop, converge, insert, pipe, nthArg} = R
const halfLength = compose (
Math .floor,
divide (__, 2),
prop ('length')
)
const insertMiddle = converge (insert, [pipe (nthArg (1), halfLength), nthArg (0), nthArg (1)])
console .log (insertMiddle (42, [1, 2, 3, 4, 5, 6]))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
我们甚至可以全力以赴并内联 halfLength
const insertMiddle = converge (insert, [
pipe (nthArg (1), prop ('length'), divide (__, 2), Math .floor),
nthArg (0),
nthArg (1)
])
同样,作为一个学习练习,这很好。但我发现其中任何一个都比一个简单的函数可读性差很多,只使用了一点 Ramda:
const insertMiddle = (x, xs) =>
insert ((xs .length >> 1), x, xs)
或普通版本:
const insertMiddle = (x, xs, mid = xs .length >> 1) =>
[... xs .slice (0, mid), x, ... xs .slice (mid)]