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. It's like R.prepend
/ R.append
, but it shoves a value into the middle of a list instead.
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
.
Am I going about this the right way? What happens next?
How does:
x => foo(bar(x), x)
or 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). If with change the order of the last two parameters of R.insert (value & array), we can use it to create 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. 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. (Disclaimer: I'm a Ramda author.) useWith
, converge
, and nthArg
are prominent among these.
We can use converge
and nthArg
to get this to work:
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
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:
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)]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.