根据维基百科关于side effect的词条,提出一个例外是一个副作用。考虑下面这个简单的python函数:
def foo(arg):
if not arg:
raise ValueError('arg cannot be None')
else:
return 10
使用foo(None)
调用它时,总是会遇到异常。同样的输入,同样的输出。它在引用上是透明的。为什么这不是一个纯函数?
发布于 2012-05-23 12:35:27
只有当您观察到异常,并根据它做出更改控制流的决策时,才会违反纯洁性。实际上,抛出异常值在引用上是透明的--它在语义上等同于非终止或其他所谓的bottom values.
如果一个(纯)函数不是total,那么它的计算结果是最低值。如何编码最低值取决于实现-它可能是一个异常;或者不终止,或者除以零,或者其他一些失败。
考虑纯函数:
f :: Int -> Int
f 0 = 1
f 1 = 2
这并不是为所有输入定义的。对于一些人来说,它的计算结果是底部。该实现通过抛出异常来对此进行编码。它应该在语义上等同于使用Maybe
或Option
类型。
现在,只有在观察最低值时才会破坏引用透明性,并根据它做出决策--这可能会引入非确定性,因为可能会抛出许多不同的异常,而您不知道是哪一个。因此,捕获异常是在Haskell的IO
monad中进行的,而生成所谓的"imprecise" exceptions则完全可以完成。
因此,引发异常本身就是一种副作用的说法是不正确的。问题在于是否可以基于异常值修改纯函数的行为,从而破坏引用透明性。
发布于 2012-05-22 13:43:40
从第一行开始:
“在计算机科学中,如果一个函数或表达式除了返回值之外,还修改了某些状态,或者与调用函数或外部世界有可观察到的交互作用,则称其具有副作用。”
它修改的状态是程序的终止。来回答你的另一个问题,为什么它不是一个纯函数。该函数不是纯粹的,因为抛出异常会终止程序,因此它有副作用(您的程序结束)。
发布于 2012-05-22 13:43:55
引用透明性也是用计算本身的结果替换计算(例如函数调用)的可能性,如果你的函数引发异常,你就不能这样做。这是因为异常不会占用计算的一部分,但它们需要被捕获!
https://stackoverflow.com/questions/10703232
复制相似问题