Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the raising of an exception a side effect?

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?

like image 887
canadadry Avatar asked May 22 '12 13:05

canadadry


People also ask

What are the problems if the exception is raised?

When an exception is raised, no further statements in the current block of code are executed. Unless the exception is handled (described below), the interpreter will return directly to the interactive read-eval-print loop, or terminate entirely if Python was started with a file argument.

What does it mean to raise an exception?

raise allows you to throw an exception at any time. assert enables you to verify if a certain condition is met and throw an exception if it isn't. In the try clause, all statements are executed until an exception is encountered. except is used to catch and handle the exception(s) that are encountered in the try clause.

Why would you raise an exception?

By raising a proper exception, it will allow other parts of your code to handle the exception properly, such that the execution can proceed. In the above code, we first define a function, read_data , that can read a file.

When should you raise exceptions?

Exceptions should be used for exceptional situations outside of the normal logic of a program. In the example program an out of range value is likely to be fairly common and should be dealt with using normal if-else type logic. (See the programming exercises.)


1 Answers

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.

like image 65
Don Stewart Avatar answered Sep 28 '22 05:09

Don Stewart