jfmengels/eslint-plugin-fp

RCF: 'Pure' rule

Closed this issue · 4 comments

Would a 'pure' that enforced functional purity be a welcome addition to this project?

The premise sounds nice, but I am not sure what you are talking about or what it would entail. Could you develop a bit more? With examples of when errors would be reported and when it would not.

/* eslint fp/pure: 2 */

var foo = 'foo'

// *Invalid*, pure function accessing external state
function some() {
  console.log(foo)
  return 'loo'
}

// *Invalid*, pure function must have return value
function bar() {
  const foo = 'foo'
  console.log(foo)
}

Not returning a value

This is actually handled by no-nil. It forbids using undefined and nil, and since not returning a value makes it return undefined, it also forbids not returning anything. I was thinking to maybe split this rule into two (one forbidding the use of undefined/null), and one enforcing that a function returns a value. Would love to discuss that if you have some opinion on it :)

Accessing external state

var foo = 'foo'

// *Invalid*, pure function accessing external state
function some() {
  console.log(foo)
  return 'loo'
}

IMO, this is not a good rule to have. If you want to do functional programming, or at least use pure functions up to a certain degree, you will need to use closures, which is some state defined in a location external to your function.

function multMByTwoTimesN(n) {
  const twoTimesN = 2 * n; // trivial example, but twoTimesN is defined external to the inner function
  return function(m) {
   return m * twoTimesN;
  };
}

Also, you would not be able to define constants shared by multiple functions

const PI = 3.14159;
const getPerimeter = radius => 2 * radius * PI;

The thing is, accessing external data does not make your function impure. Accessing external mutable data (which you probably mean when you say state), or mutating it, is.

A lot of the rules in this plugin attempt to forbid mutation (no-let, no-mutation, no-mutating-assign, no-mutating-methods, no-this, ...). Since this is JavaScript, it will always be possible to avoid do some mutation, but I hope that the developers' discipline will get the last bit that we can't catch with an ESLint rule. If your app is free from mutation, then accessing external data is fine and you do not need such a rule.

Another thing that forbidding the access to external variables would unfortunately induce, is forbidding the use of external functions (as they might be stateful, and implementation-wise it's often hard/not possible to determine whether a variable references data or a function).


This plugin as a whole attempts to do what you are aiming for. I do not think it is possible to make it into one rule, and have thus split it into several functions. Which has the added benefit that projects that are less bent on having pure functions can still use some rules.

I'd suggest to use the plugin with more rules turned on. If you feel some rules are lacking, or some could be added, please come back and comment/create a new issue :)

I think using the plugin with multiple rules turned on would suffice. Thanks