R.reduce(
(acc, x) => R.compose(
R.flip(R.prepend)(acc),
R.sum,
R.map(R.add(1))
)([x,...acc]),
[0]
)([13, 28])
The first thing to observe is all Ramda functions are curried, that means you can do partial functions, for example, R.add
receives 2 numbers as arguments and returns 1 number.
const result = R.add(2, 3)
But, how Ramda functions are curried, we can create partial functions.
const add2 = R.add(2)
const result = add2(3)
That being said, let's take a look at all functions that are used in this piece of code step by step
R.reduce
is basically transforming the array [13, 28]
in another array and the initial value for those iterations is [0]
Let's talk about the main function that will be called in each iteration of the R.reduce
R.compose(
R.flip(R.prepend)(acc),
R.sum,
R.map(R.add(1))
)([x,...acc])
R.compose is a nice way to create a chain of function calls, passing the result of each computation for the next one. One thing to notice is R.compose
will performs the functions right to left.
So in that example this will be the call order:
1 - R.map(R.add(1)) 2 - R.sum 3 - R.flip(R.prepend(acc))
Initial argument for this chain is [x, ...acc]
So, like I said before all Ramda functions are curried. R.add(1)
is basically creating a new function that takes one argument and sums with 1.
R.map
receives 2 arguments, the first one is a function that receives one value and should return another value and the second one is a list of values. The main idea here is R.map
will get a list of values and will apply one transformation function in order to return a new list of values.
In our example, R.map(R.add(1))
will receive [x, ...acc]
and add 1 to each item of this list.
This step will receive a list of values from the last computation (R.map(R.add(1))
) and will return one number containing the sum of all values of this list
R.prepend is a function that receives 2 arguments, a value and a list of items and returns a list with the first argument of this function as the first element followed by the second argument of the function, a list.
So, the signature is: a -> [a] -> [a]
Because this signature we have a problem here! The result of the last step (R.sum) is a number, and the last argument that R.prepend needs is a list, so the trick is to use
R.flipto create a new function that change order of the arguments, so the signature of
R.flip(R.prepend)is:
[a] -> a -> [a], this way
R.flip(R.prepend)(acc)` will be expecting a unit value then will return a new list.
To summarize, R.compose will return a list of numbers.
Now, I think we could show all the iterations to show step by step what is happening.
R.reduce(
(acc, x) => R.compose(
R.flip(R.prepend)(acc),
R.sum,
R.map(R.add(1))
)([x,...acc]),
[0]
)([13, 28])
So, the first iteration will start as:
- acc === [0]
- x === 13
R.compose will receive [13, 0]
as argument.
R.map(R.add(1))
will receive[13, 0]
and returns[14, 1]
R.sum
will receive[14, 1]
and returns 15R.flip(R.prepend)([0])
will receive 15 and returns[15, 0]
The result of the first iteration is [15, 0]
Second iteration:
- acc === [15, 0]
- x === 28
R.compose will receive [28, 15, 0]
as argument.
R.map(R.add(1))
will receive[28, 15, 0]
and returns[29, 16, 1]
R.sum
will receive[29, 16, 1]
and returns 46R.flip(R.prepend)([15, 0])
will receive 46 and returns[46, 15, 0]
The result of the first iteration is [46, 15, 0]
The final result is [46, 15, 0]