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 的函数。


我这样做正确吗?接下来会发生什么?

如何:

免费获得积分?

用两个函数调用的 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 在其中很突出。

我们可以使用 convergenthArg 让它工作:

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)]