javascriptreduxstatepure-function

Is this not a pure function?


I am learning state management for web development, and come across this redux tutorial with the pure function as below. However the statement : "action.todo.id = state.todos.length + 1;" makes me suspect this pure function was ... IMPURE. Please enlighten me, thanks!

export function rootReducer(state: IAppState, action): IAppState {

    switch (action.type) {
        case ADD_TODO:
            action.todo.id = state.todos.length + 1;    
            return Object.assign({}, state, {
                todos: state.todos.concat(Object.assign({}, action.todo)),
                lastUpdate: new Date()
            })

        case TOGGLE_TODO:
            var todo = state.todos.find(t => t.id === action.id);
            var index = state.todos.indexOf(todo);
            return Object.assign({}, state, {
                todos: [
                    ...state.todos.slice(0, index),
                    Object.assign({}, todo, {isCompleted: !todo.isCompleted}),
                    ...state.todos.slice(index+1)
                ],
                lastUpdate: new Date()
            })
        case REMOVE_TODO:
            return Object.assign({}, state, {
                todos: state.todos.filter(t => t.id !== action.id),
                lastUpdate: new Date()
            })
        case REMOVE_ALL_TODOS:
            return Object.assign({}, state, {
                todos: [],
                lastUpdate: new Date()
            })
    }
    return state;
}

Solution

  • TL;DR - no it is not.

    Let's examine the definition of a pure function. From wikipedia:

    In computer programming, a pure function is a function that has the following properties:

    1. Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).

    2. Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).

    Although your function does conform to the second condition, using new Date() - makes it impure.

    The reason for its impurity in your case is the fact that the date is different for each of the functions invocation - regardless of the parameters passed.

    In order to make it pure, you should pass the date as an additional parameter which will allow you to have the same output for the same input.

    Zaptree had also mentioned that mutating the length of your item IDs, i.e action.todo.id = state.todos.length + 1 is impure as it might affect other parties referencing to it.