Why is the raising of an exception a side effect?
functional-programming, side-effects
Solution
Purity is only violated if you observe the exception, and make a decision based on it that changes the control flow. Actually throwing an exception value is referentially transparent -- it is semantically equivalent to non-termination or other so-called bottom values.
If a (pure) function is not total, then it evaluates to a bottom value. How you encode the bottom value is up to the implementation - it could be an exception; or non-termination, or dividing by zero, or some other failure.
Consider the pure function:
f :: Int -> Int
f 0 = 1
f 1 = 2
This is not defined for all inputs. For some it evaluates to bottom. The implementation encodes this by throwing an exception. It should be semantically equivalent to using a `Maybe` or `Option` type.
Now, you only break referential transparency when you observe the bottom value, and make decisions based on it -- which could introduce non-determinism as many different exceptions may be thrown, and you can't know which one. So for this reason catching exceptions is in the `IO` monad in Haskell, while generating so-called "imprecise" exceptions can be done purely.
So it is just not true that raising an exception is a side effect as such. It is whether or not you can modify the behavior of a pure function based on an exceptional value -- thus breaking referential transparency -- that is the issue.
Problem
According to the wikipedia entry for side effect, raising an exception constitutes a side effect. Consider this simple python function: ``` def foo(arg): if not arg: raise ValueError('arg cannot be None') else: return 10 ``` Invoking it with `foo(None)` will always be met with an exception. Same input, same output. It is referentially transparent. Why is this not a pure function?