为什么引发异常会产生副作用? [英] Why is the raising of an exception a side effect?
问题描述
根据 副作用 的维基百科条目,引发异常构成副作用.考虑这个简单的 Python 函数:
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
使用 foo(None)
调用它总是会遇到异常.同样的输入,同样的输出.它是引用透明的.为什么这不是纯函数?
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?
推荐答案
只有当您观察到异常并根据异常做出改变控制流的决定时,才会违反纯度.实际上抛出异常值在引用上是透明的——它在语义上等同于非终止或其他所谓的底部值.
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.
如果(纯)函数不是 total,则它的计算结果为底值.您如何编码底部值取决于实现 - 它可能是一个例外;或不终止,或除以零,或其他一些失败.
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.
考虑纯函数:
f :: Int -> Int
f 0 = 1
f 1 = 2
这不是为所有输入定义的.对于某些人来说,它评估为底部.该实现通过抛出异常对此进行编码.它应该在语义上等同于使用 Maybe
或 Option
类型.
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.
现在,只有当您观察底部值并根据它做出决策时,您才会破坏引用透明性——这可能会引入不确定性,因为可能会抛出许多不同的异常,并且您可以'不知道是哪一个.因此,出于这个原因,在 Haskell 的 IO
monad 中捕获异常,同时生成所谓的 不精确"的例外可以纯粹地完成.
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.
这篇关于为什么引发异常会产生副作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!