No. You can easily check if a function only does "pure-safe" operations, as described in Jon Purdy's answer, but that is IMO not enough to answer the question.
Consider this function:
function possiblyPure(x) {
if (someCheck(x)) {
return x+1; // pure code path
}
else {
console.log("I'm so unpure..."); // unpure code path
}
}
Obviously, if someCheck
is unpure, so is possiblyPure
. But, if someCheck
is pure and returns true
for every possible value of x
, possiblyPure
is pure, since the unpure code path is unreachable!
And here comes the hard part: determining whether or not someCheck
returns true for every possible input. Trying to answering that question immedately leads you into the realm of the halting problem and similar undecidable problems.
EDIT: Proof that it is impossible
There is some uncertainity wether or not a pure function must terminate on every possible input. But in both cases, the halting problem can be used to show that the pureness check is impossible.
Case A) If a pure function is required to terminate on every possible input, you have to solve the halting problem to determine whether or not the function is pure. Since this is known to be impossible, by this definition, pureness cannot be computed.
Case B) If a pure function is allowed to not terminate on some inputs, we can construct something like that:
Let's assume that isPure(f)
computes if f
is a string defining a pure function.
function halts(f) {
var fescaped = f.replace(/\"/g, '\\"');
var upf = 'function() { '+f+'("'+fescaped+'\); console.log("unpure"); }';
return isPure(upf);
}
Now isPure
has to determine whether or not f
halts on it's own source as input. If it halts, upf
is unpure; if it doesn't terminate, upf
is pure iff f
is pure.
If isPure
worked as expected (returns correct results and terminates on every input), we would have solved the halting problem(*)! Since this is known to be impossible, isPure
cannot exist.
(*) for pure JavaScript functions, which is enough to solve it for the turing machine, too.
if (rand(1000000)<2) return WRONG_ANSWER
, probing the function many times for a consistent behaviour won't help. But, if you have an access to the function definition, proof is trivial.say
callsconsole.log
which is impure thussay
is impure too.