Skip to content

Instantly share code, notes, and snippets.

@jouderianjr
Last active November 10, 2017 01:33
Show Gist options
  • Save jouderianjr/1445cc9a54e8436571a3a157327350b6 to your computer and use it in GitHub Desktop.
Save jouderianjr/1445cc9a54e8436571a3a157327350b6 to your computer and use it in GitHub Desktop.
LovelyStay
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]

1 - R.map(R.add(1))

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.

2 - R.sum

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

3 - R.flip(R.prepend)(acc)

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 ofR.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 15
  • R.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 46
  • R.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]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment