Search code examples
javascriptfunctional-programmingcurryingpartial-application

Refactor functions to use currying


I have three functions that I would like to refactor using currying but I am struggling get my head around functions that return functions. I am trying to break down and design the curried functions as a starting point.

I found this medium article that gives a very simple design.

function discount(discount) {
    return (price) => {
        return price * discount;
    }
}

const tenPercentDiscount = discount(0.1);

tenPercentDiscount(500);

At a high level, my functions get called like so:

getCatHelper(prioritisedBreeds, catDefintions, debugToggle)
  .then((breed) => setConfigData(breed, config))
  .catch(() => false);
  • if: debugToggle - it passes it mapCatValueToKey to get the cat breed
  • else: makes a network request, passes an array of catBreeds to getPriorityBreed
  • sets some data with the returned breed and a config within scope
getPriorityBreed(prioritisedBreeds, catBreeds, catDefintions)
  • calls mapCatValueToKey to map over the catBreeds and make a new array with the catDefintions
  • loops through two lists - the prioritisedBreeds and the mappedCats from above to return the priority breed
mapCatValueToKey(breed, catDefintions)
  • mapping function to map a breed (value) to a cat definition object

Here's how getCatHelper is being called:


function useCatHook(
  config: Config,
  catDefintions: any = CAT_DEFS,
  getCat: (
      prioritisedBreeds,
      catDefintions,
      debugToggle,
  ) = getCatHelper,
  debugToggle,
): any {
  const [data, setData] = useState(undefined);
  const prioritisedBreeds = Object.keys(config);

  // ...

  getCatHelper(prioritisedBreeds, catDefintions, debugToggle)
      .then(breed => setData(breed))
      .catch(() => false);

  // ...
}

My questions are:

  1. How do I design this?
  2. Should I care about the internals or just design the function and the function it returns?
  3. When refactoring, should I be working from the outer or the inner function first?

Any help would be appreciated :)


Solution

  • I wanted the hook not to know about CAT_DEFS and to pass it straight to the getCatHelper.

    I made this work:

    export function getCatHelper {
        return (
            prioritisedBreeds,
            catDefintions,
            debugToggle,
            getDataLayer = getDataFromRequest
        ) {
    
        // ...
    
        };
    }
    
    function useCatHook(
      config,
      getCat (
          prioritisedBreeds,
          catDefintions,
          debugToggle
      ) = getCatHelper(CAT_DEFS),
      debugToggle
    ) {
    
      // ...
    
    }