在类方法和闭包中,Scala中的纯函数
斯卡拉纯函数的精确定义是什么? 纯函数有一个定义,在wiki https://en.wikipedia.org/wiki/Pure_function上。 我认为这个定义是纯粹的函数式编程语言。
但是,我认为它在类方法和关闭的环境中变得复杂。
class Ave(val a: Int, val b: Int) {
def ave = (a+b)/2
}
是一个纯粹的功能? 我认为是这样,因为它没有副作用,它只取决于班级的不可变状态。 但是这实际上违背了wiki上的纯函数定义,它说纯函数通常不应该访问非局部变量。
关闭的类似问题:
def fcn(a:Int, b: Int): Unit = {
def ave = (a+b) / 2
}
对我而言,这两个都是纯函数,相当于一个“val”(统一访问原理)。
但如何严格证明? 而且,如果a和b字段是可变的,则ave不再是纯粹的功能。
class Ave2(var a: Int, var b: Int) {
def ave = (a+b)/2 // Not pure functional
}
纯函数的另一个定义来自“Scala中的函数编程”一书:
如果对于所有程序p,p的所有出现都可以被评估e的结果所替代而不影响p的含义,则表达式e是可引用的透明的。 如果对于所有引用透明的x,表达式f(x)是引用透明的,则函数f是纯粹的
那么问题是,对于一个类来说,类是一个可变状态,在类中是透明的(在我的例子中是var a,var b)? (如果是这样,那么Ave2中的ave方法变成纯函数,这是一个矛盾)
Scala中纯函数的精确定义是什么?
简短的回答:
只要闭合变量不可变,闭包不会阻止纯度。
长答案:
在真正的函数式编程语言中,非局部变量永远不会改变,所以封闭不会影响纯度。 Haskell函数是纯粹的,但Haskell使用闭包没有麻烦。 只要你的函数服从每一次被调用时都没有副作用并且对同一组参数具有相同结果的规则(换句话说,没有可变状态),你就可以得到参照透明度和纯度。 如果你对事物的理论观点进行挑剔,那么我完全理解对闭包的担忧,因为纯函数应该仅依赖于它们的论点和论点(不一定全部是这些论点)。 但是从实践的角度来看,关闭不可变变量不被认为是违反纯度。
请注意,局部可变状态不一定会危及纯度。 这是一个很滑的地形,但马丁奥德斯基有一次自己说过(如果我真的必须的话,我可以挖掘出确切的源代码,它可以是Coursera课程的一个讲座,也可以是Scala中的Programming),只要你让它们对外界不可见。 所以这个愚蠢的功能:
def addOne(i: Int) = {
var s = i
s = s + 1
s
}
可以被认为是纯粹的,即使它使用可变状态(变量s
),因为可变状态不暴露于“外部世界”,并且不会将方法addOne
的参照透明度置于危险之中。
上一篇: Pure function in Scala in the context of class methods, and closures
下一篇: Truly understanding the difference between procedural and functional