为什么引发异常会产生副作用? [英] Why is the raising of an exception a side effect?

查看:29
本文介绍了为什么引发异常会产生副作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 副作用 的维基百科条目,引发异常构成副作用.考虑这个简单的 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

这不是为所有输入定义的.对于某些人来说,它评估为底部.该实现通过抛出异常对此进行编码.它应该在语义上等同于使用 MaybeOption 类型.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆