ramda / ramda

:ram: Practical functional Javascript

Home Page:https://ramdajs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`reduce` with partial application caches results?

JamesRamm opened this issue · comments

I have found some odd behaviour in reduce.
Consider this code::

const tasks = [
   { status: 'To Do' },
   { status: 'Complete' },
   { status: 'To Do' },
   { status: 'Complete' },
   { status: 'Paused' },
   { status: 'Complete' },
   { status: 'Not Ready' },
   { status: 'In Progress' },
];


const tasksReducer = (acc, current) => {
   const key = current.status;
   acc[key] = acc[key]
      ? { count: acc[key].count + 1, status: key }
      : { count: 1, status: key };

   return acc;
};

const groupByStatus = reduce(tasksReducer, {})

// Causes count to be doubled 
groupByStatus(tasks)
groupByStatus(tasks)

It is grouping the tasks by their status (I know there are functions in ramda to do this - this is just to demonstrate the odd behaviour).

If I call groupByStatus(tasks) once, I get the right result (e.g. The first group is {"count": 2, "status": "To Do"}).

However, if I call it multiple times, the count doubles each time it is called. This seems to be related to partially applying arguments to reduce because I do not reproduce the issue if I do this:

reduce(tasksReducer, {}, tasks)
reduce(tasksReducer, {}, tasks)

Here is the issue in the ramda repl

That's because you're mutating your accumulator, you can get the desired result by doing:

const tasksReducer = (acc, current) => {
   const key = current.status;
   
   return R.pipe(
     R.mergeRight({ [key]: { status: key, count: 0 }}), // create the default value
     R.modifyPath([key, 'count'], R.inc) // increase the count by 1
   )(acc);
};

Here's a repl