3

I saw this question that shows it is impossible to programatically determine if a javascript function is pure, but is it sometimes possible to affirm that a function is pure - so something like...

function sq_a(x){ return x * x; }; // no side effects, all variables local
function sq_b(x){ return pow(x, 2); }; // if `pow` is pure, this function is pure
function sq_c(x){ return mathlib.pow(x, 2); }; // not pure, because mathlib.pow could be changed

function definitelyPure(fn){
    if(/* criteria to check if we can know for sure fn is pure */){
        return true;
    } else {
        return false;
    }
}

function isPure(fn){
    if(/* fn is pure */){
        return 0;
    } else if(/* fn might be pure */) {
        return -1;
    } else { // fn is not pure
        return 1;
    }
}

definitelyPure(sq_a); // true
definitelyPure(sq_b); // false
definitelyPure(sq_c); // false

isPure(sq_a); // 0
isPure(sq_b); // -1
isPure(sq_c); // 1

 Clarification:

I know it is not possible to determine if any javascript function is pure as answered in linked to question, but I am asking if it is possible to programatically affirm purity of some functions - as in I expect that it is possible for example sq_a using some code analysis, but I understand it is not possible for sq_b.

I am interested to know if there are any tools out there to do this already, and what criteria determine if it is possible to programatically declare a function as either pure, unknown, or impure.

2 Answers2

4

It is possible, in general, to analyse the parse tree of a function and check a set of constraints that ensure we know if the function is definitely pure:

  • If the function only calls other functions that are pure
  • And doesn't reference or modify any global variables

Then it is pure.

There is, however, a problem with doing this in Javascript (and many other dynamic languages), which is that they provide a mutable environment. You state that your function sq_b is pure, but you can't actually prove that unless you can determine the behaviour of all other code that may run before it, because that code may do something like this:

window.nextPowResult = 1;
window.pow = function (a,b) { return nextPowResult ++; }

This changes the behaviour of your function (and any other function that uses pow), and makes it non-pure. Unfortunately, determining whether or not something like this could happen is an undecidable question, so in Javascript specifically we cannot ever be certain that any function is pure, unless we have control over all code that executes in the same context.

Jules
  • 17,880
  • 2
  • 38
  • 65
2
var sneaky3 = { 
   valueOf: () => { console.log('look, a side effect'); return 3; } 
}    

>> sq_a(sneaky3) 
look, a side effect
9

As shown above, side effects can happen even in simple arithmetic operations.

Basically, the only operations that can be proven pure are operations on literals using built-in operators, like 2 + 2. This is so limited as to be useless.

JacquesB
  • 61,955
  • 21
  • 135
  • 189