参考透明度是什么意思?我曾听人描述它为“这意味着你可以用等号替换等号”,但这似乎是一个不充分的解释。


当前回答

引用透明性是函数式编程中常用的术语,它意味着给定一个函数和一个输入值,您将始终收到相同的输出。也就是说,函数中没有使用外部状态。

下面是一个引用透明函数的例子:

int plusOne(int x)
{
  return x+1;
}

对于引用透明函数,给定一个输入和一个函数,您可以用一个值替换它,而不是调用函数。所以我们不用参数5来调用+ one,我们可以用6来代替它。

另一个很好的例子是一般的数学。在数学中,给定一个函数和一个输入值,它总是映射到相同的输出值。F (x) = x + 1。因此,数学中的函数是指透明的。

这个概念对研究人员来说很重要,因为它意味着当您拥有一个引用透明的函数时,它有助于实现简单的自动并行化和缓存。

引用透明性总是用在像Haskell这样的函数式语言中。

--

与之相反的是参照不透明的概念。这句话的意思正好相反。调用该函数可能并不总是产生相同的输出。

//global G
int G = 10;

int plusG(int x)
{//G can be modified externally returning different values.
  return x + G;
}

另一个例子是面向对象编程语言中的成员函数。成员函数通常对其成员变量进行操作,因此是引用不透明的。成员函数当然可以是引用透明的。

还有一个例子是从文本文件中读取并打印输出的函数。这个外部文本文件可以随时更改,因此该函数将是引用不透明的。

其他回答

下面的答案我希望能补充并限定有争议的第一个和第三个 的答案。

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中,有两种语言的清晰度:

被建模的那个,目标语言 建模的语言,元语言

2、由于对象和元语言的紧密性,它们可能会被混淆。

作为一名语言实现者,我发现我需要经常记住这个区别。

所以Reddy教授,我可以这样解释你吗?

在函数式编程和语义的上下文中,术语引用 透明度不是指的透明。

[这是我3月25日的回答的后记,旨在使讨论更接近函数式/命令式编程的关注点。]

函数式程序员关于引用透明性的想法似乎在三个方面不同于标准的概念:

Whereas the philosophers/logicians use terms like "reference", "denotation", "designatum" and "bedeutung" (Frege's German term), functional programmers use the term "value". (This is not entirely their doing. I notice that Landin, Strachey and their descendants also used the term "value" to talk about reference/denotation. It may be just a terminological simplification that Landin and Strachey introduced, but it seems to make a big difference when used in a naive way.) Functional programmers seem to believe that these "values" exist within the programming language, not outside. In doing this, they differ from both the philosophers and the programming language semanticists. They seem to believe that these "values" are supposed to be obtained by evaluation.

例如,维基百科关于参考透明度的文章今天早上说:

如果一个表达式可以用它的值替换而不改变程序的行为(换句话说,在相同的输入上产生相同的效果和输出的程序),那么这个表达式就是引用透明的。

This is completely at variance with what the philosophers/logicians say. They say that a context is referential or referentially transparent if an expression in that context can be replaced by another expression that refers to the same thing (a coreferential expression). Who are these philosophers/logicians? They include Frege, Russell, Whitehead, Carnap, Quine, Church and countless others. Each one of them is a towering figure. The combined intellectual power of these logicians is earth-shattering to say the least. All of them are unanimous in the position that referents/denotations exist outside the formal language and expressions within the language can only talk about them. So, all that one can do within the language is to replace one expression by another expression that refers to the same entity. The referents/denotations themselves do not exist within the language. Why do the functional programmers deviate from this well-established tradition?

有人可能会认为编程语言语义学家可能误导了他们。但是,他们没有。

Landin:

(a)每个表达式有一个 嵌套子表达式结构,(b)每个子表达式 表示某物(通常是数字、真值或 数值函数),(c)表达式表示的东西, 也就是说,它的“值”只取决于它的子元素的值 表达式,而不是它们的其他属性。(添加重点)

Stoy:

关于表达式,唯一重要的是它的值,任何子表达式都可以 用其他同等价值的东西代替[强调]。此外,在一定范围内,表达式的值无论何时出现都是相同的。”

伯德和瓦德勒:

表达式的值仅取决于其组成部分的值 表达式(如果有)和这些子表达式可以被其他表达式自由替换 具有相同的价值[强调]。

So, in retrospect, the efforts of Landin and Strachey to simplify the terminology by replacing "reference"/"denotation" with "value" might have been injudicious. As soon as one hears of a "value", there is a temptation to think of an evaluation process that leads to it. It is equally tempting to think of whatever the evaluation produces as the "value", even though it might be quite clear that that is not the denotation. That is what I gather to have happened to the concept of "referential transparency" in the eyes of functional programmers. But the "value" that was being spoken of by the early semanticists is not the result of an evaluation or the output of a function or any such thing. It is the denotation of the term.

一旦我们将一个表达式(经典哲学家话语中的“引用”或“外延”)的所谓“价值”理解为一个复杂的数学/概念对象,各种可能性就会打开。

Strachey interpreted variables in imperative programming languages as L-values, as mentioned in my March 25 answer, which is a sophisticated conceptual object that does not have a direct representation within the syntax of a programming language. He also interpreted commands in such languages as state-to-state functions, another instance of a complex mathematical object that is not a "value" within the syntax. Even a side-effecting function call in C has a well-defined "value" as a state transformer that maps states to pairs of states and values (the so-called "monad" in functional programmers' terminology).

The reluctance of functional programmers to call such languages "referentially transparent" merely implies that they are reluctant to admit such complex mathematical/conceptual objects as "values". On the other hand, they seem perfectly willing to call a state transformer a "value" when it is put in their own favourite syntax and dressed up with a buzz word like "monad". I have to say that they are being entirely inconsistent, even if we grant it to them that their idea of "referential transparency" has some coherence.

A bit of history might throw some light on how these confusions came into being. The period between 1962 to 1967 was a very intensive one for Christopher Strachey. Between 1962-65, he took a part-time job as a research assistant with Maurice Wilkes to design and implement the programming language that came to be known as CPL. This was an imperative programming language but was meant to have powerful functional programming language capabilities as well. Landin, who was an employee of Strachey in his consultancy company, had a huge influence on Strachey's view of programming languages. In the landmark 1965 paper "Next 700 programming languages", Landin unabashedly promotes functional programming languages (calling them denotative languages) and describes imperative programming languages as their "antithesis". In the ensuing discussion, we find Strachey raising doubts on Landin's strong position.

... DLs形式 所有语言的子集。他们是一个有趣的子集,但只有一个 除非你习惯了,否则使用起来很不方便。我们需要 因为目前我们还不知道如何构造 使用包含命令和跳转的语言进行证明。(添加重点)

In 1965, Strachey took the position of a Reader at Oxford and seems to have worked essentially full-time on developing a theory of imperatives and jumps. By 1967, he was ready with a theory, which he taught in his course on "Fundamental concepts in programming languages" in a Copenhagen summer school. The lecture notes were supposed to have been published but "unfortunately, because of dilatory editing, the proceedings never materialized; like much of Strachey’s work at Oxford, however, the paper had an influential private circulation." (Martin Campbell-Kelly)

由于人们依赖二手资料和道听途说,很难获得斯特雷奇的作品可能会导致混淆的传播。但是,既然“基本概念”在网上很容易找到,就没有必要依靠猜测了。我们应该读一读,然后对斯特雷奇的意思作出自己的判断。特别是:

In section 3.2, he deals with "expressions" where he talks about "R-value referential transparency". His section 3.3 deals with "commands" where he talks about "L-value referential transparency". In section 3.4.5, he talks about "functions and routines" and declares that "any departure of R-value referential transparency in a R-value context should either be eliminated by decomposing the expression into several commands and simpler expressions, or, if this turns out to be difficult, the subject of a comment."

如果不理解l值、r值和其他填充命令式程序员概念宇宙的复杂对象之间的区别,任何关于“引用透明性”的讨论从根本上都是错误的。

一个表达式是引用透明的,如果它可以用它的值替换,而不改变算法,产生的算法在相同的输入上具有相同的效果和输出。