fs2005
fs2005

Reputation: 591

Pure functions in javascript

I understand functions need to be pure in order to avoid side-effects. The the following function for example:

//Approach 1
buildValidationErrors(state){

  let validationErrors = [];
  
  if(state.name === null)
  {
    validationErrors.push("Name");
  }
  
  if(state.email === null)
  {
    validationErrors.push("Email");
  }
  
  if(state.mobile === null)
  {
    validationErrors.push("mobile");
  }
  
  return validationErrors;
}

//Approach 2
_buildError(state,itemName,validationErrors){
  if(state[itemName] === null){
     validationErrors.push(itemName);
  }
}

buildValidationErrors1(state){

  let validationErrors = [];
  
 _buildError(state,"Name",validationErrors );
 _buildError(state,"Email",validationErrors);
 _buildError(state,"mobile",validationErrors);
  
  return validationErrors;
}

In "Approach 1", you have a long function that builds an array. In "Approach 2" I am extracting the reusable logic to "_buildError" to avoid duplication of logic.

However, in Approach 2, the parameter validationErrors is passed in and it is updated as well causing the function to become 'impure' to my understanding.

From that perspective, can the function be pure and compact?

Upvotes: 1

Views: 121

Answers (2)

mplungjan
mplungjan

Reputation: 177691

I would consider

_buildError(state,itemName){
   return state[itemName] === null ? itemName : null;
}

// reduce if you need more than one thing in the validation array

let validationErrors = ["Name","Email","mobile"]
  .reduce((acc,item) => {
   if (_buildError(state,item)) acc.push({item,something:state[item].something}); return acc },
  [] );

// filter if you just need the item name

let validationErrors = ["Name","Email","mobile"]
  .filter(item => _buildError(state,item));

Upvotes: 1

Eriks Klotins
Eriks Klotins

Reputation: 4180

You can avoid passing the errors array by merging the results outside the _buildError() function:

_buildError(state,itemName){
  return state[itemName] === null ? itemName : null; 
}

buildValidationErrors1(state){

  let validationErrors = [];
  
  validationErrors.push(
     _buildError(state,"Name"),
     _buildError(state,"Email"),
     _buildError(state,"mobile")
  ).filter((a)=> a !== null);


  
  return validationErrors;
}

However, that does not really change the purity of the function. In your 2nd example, the function depends and change only its parameters, thus it is "pure" enough for automated tests and other practical purposes.

Upvotes: 1

Related Questions