Sepehr Sobhani
Sepehr Sobhani

Reputation: 882

Functional Ramda Passing function parameter outside of scope

Take the following example imperative JavaScript example:

getAnimalList = (hasCat) => {
  const baseAnimals = { dog: animLib.dog(), bear: animLib.bear()};
  if(hasCat){
    baseAnimals.cat = animLib.cat();
  }
  return baseAnimals
}

I am trying to write this code in a functional style with Ramda, but the only way I can do so is by having the functions reach outside of scope:

getAnimalList = (hasCat) => {
  const baseAnimals = { dog: animLib.dog(), bear: animLib.bear()};
  return when(always(hasCat), merge({hasCat: animLib.cat()}))(baseAnimals)
}

Leaving aside how animLib is outside of scope, the way I would fix has hasCat from being pass from the outside(if this is a problem at all) is the following:

getAnimalList = (hasCat) => {
  const baseAnimals = { dog: animLib.dog(), bear: animLib.bear()};
  const mergeCat = when(compose(equals(true), prop('hasCat')), 
              compose(merge({hasCat: animLib.cat()}), prop('baseAnimals')));
 return mergeCat({hasCat: hasCat, baseAnimals: baseAnimals});
}

But this makes the code incredibly verbose. Is there a better way to do this? Or is the verbosity just the cost of keeping the code more pure.

Upvotes: 0

Views: 320

Answers (1)

Scott Sauyet
Scott Sauyet

Reputation: 50787

It seems to me that this would do fine:

getAnimalList = (animLib, hasCat) => {
  const baseAnimals = { dog: animLib.dog(), bear: animLib.bear()};
  return hasCat ? merge({hasCat: animLib.cat()}, baseAnimals) : baseAnimals;
}

Because Ramda's when and ifElse are based around predicate functions rather than boolean values, using them seems to be overkill here.

Obviously if you want a version that has animLib in scope, you can curry this function, either with something like Ramda's curry or just by changing to

getAnimalList = (animLib) => (hasCat) => { /* ... */ }

Then you can create newAnimalList = getAnimalList(myAnimLib).

Upvotes: 1

Related Questions