ksadjad
ksadjad

Reputation: 603

Convert ramda to normal js

I have a legacy code in ramda and I have a hard time figuring what it does. How can I convert ramda function to a simple javascript? my function goes as follows:

R.forEach(
      R.compose(
        vm.importAll,
        b =>
          R.compose(
            R.map(R.merge(R.pick(["index"])(b))),
            R.prop("transactions")
          )(b)
      )
    )

Upvotes: 1

Views: 827

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50787

user633183 correctly described what that code was designed to do. To me this code demonstrates a misunderstanding of what Ramda is for. It mixes Ramda techniques with others in an undisciplined manner.

My initial vanilla JS rewrite looks something like this:

const submitTransactions = (xs) => xs .forEach (
  ({transactions, index}) => 
    vm .importAll (transactions .map (t => ({...t, index}) ))
)

const input = [
  {index: 42, transactions: [{foo: 'bar'}, {foo: 'baz'}]},
  {index: 51, transactions: [{foo: 'qux'}, {foo: 'corge'}]}
]

const vm = { // dummy -- I have no idea what this actually does
  importAll: (xs) => console .log (`importing all of ${JSON .stringify (xs)}`)
}

submitTransactions (input)

But I still don't like this. I would rather push the side effect of vm.importAll further out toward the edges of my system, and so I would prefer this version:

const transformTransactions = (xs) => xs .map (
  ({transactions, index}) => 
    transactions .map (t => ({...t, index}) )
)

const input = [
  {index: 42, transactions: [{foo: 'bar'}, {foo: 'baz'}]},
  {index: 51, transactions: [{foo: 'qux'}, {foo: 'corge'}]}
]

const vm = { // dummy -- I have no idea what this actually does
  importAll: (xs) => console .log (`importing all of ${JSON .stringify (xs)}`)
}

transformTransactions (input) .forEach (vm .importAll)

This is standard ES6 code. I don't know if it meets your criteria of "normal" or "simple".

You could rewrite this using Ramda functions, and in a simpler manner than displayed in the original, but I think it would not be as simple as the original, so there seems no need. One such version might look like this:

const {map, lift, compose, merge, pick, prop} = R

const transformTransactions = map (
  lift (map) (
    compose (merge, pick (['index']) ), 
    prop ('transactions')
  )
)

While this is not horrible, it offers no clear advantages over the previous version.

Finally, depending up how vm.importAll works, it might be better to make a single call to it with all the data rather than the multiple calls implied here. Just changing to flatMap would make this possible:

const submitTransactions = (xs) => xs .flatMap (
  ({transactions, index}) => 
    transactions .map (t => ({...t, index}) )
)

vm .importAll (submitTransactions (input))

I'm one of the founders of Ramda and a heavy user of it. But it has a specific purpose: to make some functional programming techniques more accessible in Javascript. I honestly wish we'd never included .forEach, as it makes it too easy to use Ramda for things it was not designed for.

This is also the first time I've heard "legacy" associated with Ramda code. I guess either the library or I have started to get old! :-)

Upvotes: 4

Mulan
Mulan

Reputation: 135197

The code creates a function which takes as input the data structure below -

[ { index: 123
  , transactions: [ { ... }, ... ]
  }
, { index: 456
  , transactions: [ { ... }, ... ]
  }
, ...
]

For each object in the input array, o, it builds an array of the object's transactions, o.transactions, adding the object's index, o.index, to each new transaction object.

The intermediate state looks like this, where ... represents individual transaction data -

[ { index: 123, ... }, { index: 123, ... }, { index: 123, ... }, ... ] 

This array is passed to vm.importAll, ie -

vm.importAll([ { index: 123, ... }, ... ])

The process is repeated for each object in the input array -

vm.importAll([ { index: 456, ... }, ... ])
vm.importAll([ ... ])

Enjoy writing the non-Ramda version!

Upvotes: 5

Related Questions