简体   繁体   English

Ramda 转换为自由点样式

[英]Ramda Converting to Free-Point Style

I haven't really found a good resource for this sort of thing.我还没有真正找到这种事情的好资源。 Apologies in advance if this question has been asked, though I couldn't quite find the answer (perhaps due to a lack of knowing how to search.如果有人问过这个问题,请提前道歉,尽管我找不到答案(可能是因为不知道如何搜索。

I have this function.我有这个 function。 It's like R.prepend / R.append , but it shoves a value into the middle of a list instead.就像R.prepend / R.append ,但它将一个值推到列表的中间。

const insertMiddle = (val, arr) => 
  R.insert(Math.floor(arr.length/2), val, arr);

I'm just learning functional programming, so I'm writing a program with as much free-point-style as possible.我只是在学习函数式编程,所以我正在编写一个尽可能多的自由点风格的程序。 Even if that takes away from readability a bit, I just like to see it done.即使这会影响可读性,我只是希望看到它完成。 Bend my brain to start thinking functionally and seeing how to solve problems that way.弯曲我的大脑,开始功能性地思考,看看如何以这种方式解决问题。

Here's what I've done:这是我所做的:

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

This of course isn't free-point yet.这当然还不是自由点。

Here is ostensibly the next step:这显然是下一步:

const insertMiddle = (val, arr) => 
  R.insert(R.__, val)(halfLength(arr), R.identity(arr));

Now if I can get (halfLength(arr), R.identity(arr)) to be point-free, I'll be left with a function that just needs val .现在,如果我可以得到(halfLength(arr), R.identity(arr))是无点的,我将得到一个只需要val的 function 。


Am I going about this the right way?我会以正确的方式解决这个问题吗? What happens next?接下来发生什么?

How does:如何:

  • x => foo(bar(x), x) or x => foo(bar(x), x)
  • x => foo(bar(x),baz(x))

become point free?成为免费点?

The R.chain called with two functions - chain(f, g)(x) is the equivalent of f(g(x), x).使用两个函数调用的 R.chain -chain(f, g)(x) 等效于 f(g(x), x)。 If with change the order of the last two parameters of R.insert (value & array), we can use it to create insertMiddle :如果改变 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 does offer tools to make it easier to write points-free code. Ramda 确实提供了一些工具,可以更轻松地编写无点代码。 And if you are just fiddling around, trying to see how they work, we can do all sorts of things with them.如果你只是在摆弄,想看看它们是如何工作的,我们可以用它们做各种各样的事情。 But I would reiterate that the goal should be understandable code.但我要重申,目标应该是可理解的代码。 Use points-free when it helps with readability;在有助于提高可读性时使用免积分; skip it when it doesn't.没有的时候跳过它。

There are a few Ramda functions specifically designed for this.有一些专门为此设计的 Ramda 函数。 (Disclaimer: I'm a Ramda author.) useWith , converge , and nthArg are prominent among these. (免责声明:我是 Ramda 的作者。) useWithnthArg converge突出的。

We can use converge and nthArg to get this to work:我们可以使用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>

We could even go whole-hog and inline halfLength我们甚至可以 go Whole-hog 和 inline halfLength

const insertMiddle = converge (insert, [
  pipe (nthArg (1), prop ('length'), divide (__, 2), Math .floor), 
  nthArg (0), 
  nthArg (1)
])

Again, as a learning exercise, this is fine.同样,作为一个学习练习,这很好。 But I find either of those a lot less readable than a simple function, using only a bit of Ramda:但我发现其中任何一个都比简单的 function 可读性差很多,只使用一点 Ramda:

const insertMiddle = (x, xs) =>
  insert ((xs .length >> 1), x, xs)

or a plain vanilla version:或普通的香草版本:

const insertMiddle = (x, xs, mid = xs .length >> 1) =>
  [... xs .slice (0, mid), x, ... xs .slice (mid)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM