从scala"中的函数编程一书中,我看到"参考透明"的定义。表达式:
如果对于所有程序p,p中所有出现的e都可以被评估e的结果替换而不影响p的含义,则表达式e是引用透明的。
我有一些代码示例,我不确定它们是否具有引用透明性。
我将在可变类
的示例中使用scala.collection.mutable.StringBuilder
1
val x = new StringBuilder("Hello")
println(x.length)
println(x.length)
假设此处的代码是使用x
的完整代码。
我可以说表达式x
是一个参照透明表达式吗?
如果我更改所有x
及其值new StringBuilder("Hello")
,则程序的可观察行为不会更改:
val x = new StringBuilder("Hello")
println(new StringBuilder("Hello").length)
println(new StringBuilder("Hello").length)
2
val x = new StringBuilder("Hello")
val y = x.append("aaa")
假设此处的代码是使用x
和y
的完整代码。
我可以说y
是参考透明的,因为它在程序中根本没用过吗?
第3
def getTheClassName(n:Int):String = {
val x = new StringBuilder("hello")
for(int i=0;i<n;i++) {
x.append("world")
}
return x.getClass.getName
}
我可以说x
是参考透明的吗?因为无论我如何用它的值替换它,返回值都不会改变。
for all programs p
的含义是什么,它是否意味着现有的完整代码?或者可能添加的任何可能的代码?
答案 0 :(得分:2)
这意味着您可能编写包含该表达式的任何可能的程序p
。恰当地,这应该根据语言或一组可能的程序来定义。因此,您的x
在语言中是引用透明的,其中唯一有效的程序是您编写的。您的y
在Scala子集中是引用透明的,您不允许在.append
上调用StringBuilder
。但这些并不是特别有趣的语言。
大多数时候,当人们谈论&#34;引用透明&#34;表达式,它们(隐含地)意味着像Scalazzi safe subset of Scala这样的东西,它足以表达(所有?)有用的Scala程序,但足够安全,可以推理。因为当然,如果你被允许打电话,例如System.identityHashCode()
,大多数据称是&#34;参考透明&#34;表达式实际上不是。
当然,最重要的定义是可操作的定义;什么是&#34;参考透明&#34;最终取决于你想用它做什么。一个重要的用例是编译器/库优化:我们不希望编译器执行您在示例1中给出的替换,因为对于大多数程序来说这&#34;优化&#34;会改变程序的含义。但是我们很高兴编译器通过内联不可变常量来优化我们的程序,因为我们的程序&#34;不应该&#34;#34;取决于特定常数的identityHashCode
是什么。
答案 1 :(得分:1)
据我所知,表达&#39; e&#39;在引用方面是透明的,它是否适用于所有可能的程序&#39; p&#39;。
它可以是&#34;参考透明的&#34;对于具体的节目&#39; p&#39;,但如果你可以写另一个节目&#39; px&#39;这将违反&#34;替换规则&#34;,这意味着表达不是参照透明的。
import scala.collection.mutable
val b = new mutable.StringBuilder("Hello")
def e = b.length
def p0 = {
val l1 = e
val l2 = e
l1 + l2
}
def p1 = {
val l1 = e
b.append("World")
val l2 = e
l1 + l2
}
可以建立程序&#39; p&#39;这将违反&#34; e中的e可以用e&#34; - 这意味着&#39; e&#39;不是指称透明的。在可变状态下,构建此程序非常容易。
在p0中我们可以说e是参考透明的,但是p1很容易打破它。