参考透明度是什么意思?我曾听人描述它为“这意味着你可以用等号替换等号”,但这似乎是一个不充分的解释。
当前回答
当我读到被接受的答案时,我以为我在不同的页面上,而不是在stackoverflow上。
引用透明性是定义纯函数的一种更正式的方式。因此,如果一个函数在相同的输入上始终产生相同的结果,那么它就是引用透明的。
let counter=0
function count(){
return counter++
}
这不是引用透明的,因为返回值取决于外部变量“counter”,并且它一直在变化。
这是我们如何使它的参考透明:
function count(counter){
return counter+1
}
现在这个函数是稳定的,并且在提供相同的输入时总是返回相同的输出。
其他回答
引用透明性可以简单地表述为:
一个表达式在任何上下文中总是求相同的结果[1], 一个函数,如果给定相同的参数两次,必须产生相同的结果两次。
例如,编程语言Haskell是一种纯函数式语言;这意味着它是引用透明的。
一个表达式是引用透明的,如果它可以用它的值替换,而不改变算法,产生的算法在相同的输入上具有相同的效果和输出。
下面的答案我希望能补充并限定有争议的第一个和第三个 的答案。
Let us grant that an expression denotes or refers to some referent. However, a question is whether these referents can be encoded isomorphically as part of expressions themselves, calling such expressions 'values'. For example, literal number values are a subset of the set of arithmetic expressions, truth values are a subset of the set of boolean expressions, etc. The idea is to evaluate an expression to its value (if it has one). So the word 'value' may refer to a denotation or to a distinguished element of the set of expressions. But if there is an isomorphism (a bijection) between the referent and the value we can say they are the same thing. (This said, one must be careful to define the referents and the isomorphism, as proven by the field of denotational semantics. To put an example mentioned by replies to the 3rd answer, the algebraic data type definition data Nat = Zero | Suc Nat does not correspond as expected to the set of natural numbers.)
让我们用E[·]表示一个带洞的表达式,这个表达式在某些地方也很常见 作为一个“上下文”。类c表达式的两个上下文示例是[·]+1和 (·)+ +。
让我们写[[·]]来表示接受一个表达式(不带空洞)的函数 并在某些方面传达其意义(指涉物、外延等) meaning-providing宇宙。(我借用了这个领域的符号 指涉语义学。)
让我们稍微正式地将奎因的定义改编如下: 如果给定任意两个表达式E1和E2(无孔 因此[[E1]] = [[E2]](即表达式表示/指的是 相同的referent)则[[E[E1]]] = [[E[E2]]](即填写 具有E1或E2的孔会导致表示相同的表达式 referent)。
Leibniz's rule of substituting equals for equals is typically expressed as 'if E1 = E2 then E[E1] = E[E2]', which says that E[·] is a function. A function (or for that matter a program computing the function) is a mapping from a source to a target so that there is at most one target element for each source element. Non-deterministic functions are misnomers, they are either relations, functions delivering sets, etc. If in Leibniz's rule the equality = is denotational then the double-brackets are simply taken for granted and elided. So a referentially transparent context is a function. And Leibniz's rule is the main ingredient of equational reasoning, so equational reasoning is definitely related to referential transparency.
虽然[[·]]是一个从表达式到表示法的函数,但它可以是一个 函数从表达式到“值”被理解为一个受限制的子集 表达式,和[[·]]可以理解为求值。
现在,如果E1是一个表达式,E2是一个值,我们就有了我认为大多数人在定义表达式、值和求值方面的引用透明性时的意思。但正如本页第1和第3个答案所说明的那样,这是一个不准确的定义。
像[·]++这样的上下文的问题不是副作用,而是它的值在C语言中的定义与它的含义不是同构的。函数是 不是值(好吧,指向函数的指针是),而在函数式编程语言中它们是。Landin, 斯特雷奇和表示性语义学的先驱们都很聪明 使用功能世界来提供意义。
对于命令式c类语言,我们可以(粗略地)提供语义 使用函数[[·]]的表达式:Expression -> (State -> State x Value)。
Value is a subset of Expression. State contains pairs (identifier,value). The semantic function takes an expression and delivers as its meaning a function from the current state to the pair with the updated state and a value. For example, [[x]] is the function from the current state to the pair whose first component is the current state and whose second component is the value of x. In contrast, [[x++]] is the function from the current state to the pair whose first component is a state in which the value of x is incremented, and whose second component is that very value. In this sense, the context [·]++ is referentially transparent iff it satisfies the definition given above.
我认为函数式程序员有权在 它们自然地将[[·]]作为函数从表达式恢复到值。 函数是一类值,状态也可以是值,而不是 外延。状态单子(在某种程度上)是一种用于传递(或 线程化)状态。
请注意,这个“意义”的概念是发生在观察者头脑中的事情。因此,同样的“参考”对不同的人可能意味着不同的事情。例如,我们在维基百科上有一个爱丁堡消歧页面。
在编程上下文中出现的一个相关问题可能是多态性。
也许我们应该为特殊情况下的多态(或者甚至是强制转换)取一个名字,其中不同的多态情况在语义上是等价的(而不是完全相似)。例如,数字1——可以用整数类型、复杂类型或任何其他类型表示——可以用多态方式处理)。
对于那些需要简明解释的人,我将冒险给出一个解释(但请阅读下面的披露)。
编程语言中的引用透明性促进了等式推理——您拥有的引用透明性越多,就越容易进行等式推理。例如,使用(伪)函数定义,
F x = x + x,
在这个定义的范围内,您可以(安全地)将f(foo)替换为foo + foo,而不会对在哪里执行此简化有太多限制,这很好地说明了您的编程语言具有多大的引用透明性。
例如,在C编程的意义上,如果foo是x++,那么你就不能安全地执行这个约简(也就是说,如果你要执行这个约简,你最终得到的程序将与你开始时的程序不同)。
在实际的编程语言中,你不会看到完美的引用透明性,但函数式程序员比大多数人更关心它(参考Haskell,它是一个核心目标)。
(完全披露:我是一个函数式程序员,所以从上面的答案你应该对这个解释持保留态度。)
推荐文章
- 面向对象编程,函数式编程,过程式编程
- 什么是“P=NP?”,为什么这是一个如此著名的问题?
- 为什么不可变性在JavaScript中如此重要(或需要)?
- 如何使用underscore.js作为模板引擎?
- Scala中的“提升”是什么?
- Javascript相当于Python的zip函数
- 使用array_map()访问第一级键,而不调用' array_keys() '
- functools partial是怎么做的呢?
- 过程式编程和函数式编程的区别是什么?
- 没有可变状态,你怎么能做任何有用的事情?
- 如何在Python中使用lambda排序
- 八岁小孩的大o ?
- 什么是参考透明度?
- 为什么Python不适合函数式编程?
- 什么是类型安全?