Reputation: 544
I have an array of objects
const myNumbers = [
{
top: 10,
bottom: 5,
rate: 5
},
{
top: 9,
bottom: 4,
rate: 3
},
];
I want to run a few functions that make the numbers usable before I do anything with them;
const addTen = r.add(10);
const double = r.multiply(2);
And a function that accepts the numbers and does some maths:
const process = (top, bottom, rate) => r.multiply(r.subtract(bottom, top), rate)
So my final function looks like
muNymbers.map(({ top, bottom, rate }) =>
process(addTen(top), double(bottom), rate)
);
Just looking at this code you can see both functions are already becoming very nested and not particularly clear. My real problem is slightly more complicated again, and I am struggling to see how I can make this point-free when picking different values for different operations.
Upvotes: 3
Views: 324
Reputation: 50787
If this is an exercise in writing point-free code, a solution like the one from @JeffreyWesterkamp is fine.
For production code, though, any point-free solution is going to be a lot less readable than this simple version:
const process = ({top, bottom, rate}) => ((2 * bottom) - (10 + top)) * rate;
const myNumbers = [
{ top: 10, bottom: 5, rate: 5 },
{ top: 9, bottom: 4, rate: 3 },
];
console.log(R.map(process, myNumbers));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
The point is to not make a fetish over point-free. It is a tool that sometimes makes code easier to read, easier to understand. But it's not worth using if it doesn't do so.
Don't get me wrong. I'm a big fan of point-free code, and Ramda (disclaimer: I'm one of its authors) has some useful tools to help you write it. But Ramda works just fine with other code. So use it wisely.
One other point (ahem): Ramda supplies two fairly unusual functions, useWith
and converge
, to make it easier to write point-free code. But converge
can often be replaced by the more standard lift
. It can't always be replaced, as it has some features for handling variadic functions that lift
does not supply, but when you can use lift
, I would suggest that you do so. For instance, instead of
converge(subtract, [prop('bottom'), prop('top')])
you might write
lift(subtract)(prop('bottom'), prop('top'))
There's no standard replacement for useWith
that I know of. But I would replace converge
with lift
whenever possible.
Upvotes: 3
Reputation: 7916
Here is a point-free approach. The main functions you're looking for are pipe
, evolve
and converge
. I'm not sure if this is the best way, it's just the best I could think of:
const { add, converge, evolve, map, multiply, pipe, prop, subtract } = R;
const myNumbers = [
{ top: 10, bottom: 5, rate: 5 },
{ top: 9, bottom: 4, rate: 3 },
];
const process = pipe(
evolve({
top: add(10),
bottom: multiply(2),
}),
converge(multiply, [
converge(subtract, [
prop('bottom'),
prop('top'),
]),
prop('rate'),
]),
);
console.log(map(process, myNumbers));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
Upvotes: 4