参考透明度是什么意思?我曾听人描述它为“这意味着你可以用等号替换等号”,但这似乎是一个不充分的解释。
当前回答
[这是我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值和其他填充命令式程序员概念宇宙的复杂对象之间的区别,任何关于“引用透明性”的讨论从根本上都是错误的。
其他回答
编程中的引用透明性指的是,当一个函数提供了一个输入时,它总是会为给定的输入返回相同的值。以下面的示例函数为例。
Int plusFive(int x){
return x+5
}
对于给定的输入整数x,该函数总是返回相同的值。上述函数的输出可以被其返回值所替代,并且代码的操作应该相同。例如,如果x=10,那么代码可以写成:
Int输出= + 5 (10)
OR
Int输出= 15
引用透明性可以简单地表述为:
一个表达式在任何上下文中总是求相同的结果[1], 一个函数,如果给定相同的参数两次,必须产生相同的结果两次。
例如,编程语言Haskell是一种纯函数式语言;这意味着它是引用透明的。
引用透明函数是只依赖于其输入的函数。
The term "referential transparency" comes from analytical philosophy, the branch of philosophy that analyzes natural language constructs, statements and arguments based on the methods of logic and mathematics. In other words, it is the closest subject outside computer science to what we call programming language semantics. The philosopher Willard Quine was responsible for initiating the concept of referential transparency, but it was also implicit in the approaches of Bertrand Russell and Alfred Whitehead.
就其核心而言,“参考透明度”是一个非常简单明了的概念。“指涉物”一词在分析哲学中用来谈论一个表达所指代的事物。它与我们在编程语言语义中所说的“意义”或“外延”大致相同。以Andrew Birkett的博客文章为例,“苏格兰的首都”指的是爱丁堡市。这是“referent”的一个简单例子。
一个句子中的上下文是“引用透明的”,如果用另一个引用同一实体的术语替换该上下文中的一个术语不会改变其含义。例如
苏格兰议会在苏格兰首都开会。
意思和
苏格兰议会在爱丁堡开会。
因此,“苏格兰议会在……开会”是一个指涉透明的上下文。我们可以把“苏格兰的首府”换成“爱丁堡”而不改变它的意思。换句话说,上下文只关心术语所指的内容,而不关心其他内容。也就是说,上下文是“引用透明的”。
另一方面,在句子中,
自1999年以来,爱丁堡一直是苏格兰的首府。
我们不能做这样的替换。如果我们这样做,我们会得到“Edinburgh has been Edinburgh since 1999”,这是一个疯狂的说法,并且不能传达与原句子相同的意思。所以,“Edinburgh has been…”“自1999年以来”是指不透明的(指透明的反义词)。显然,它关心的东西比这个词所指的东西更重要。是什么?
像“苏格兰的首都”这样的词被称为“限定名词”,在很长一段时间里,它们并没有让逻辑学家和哲学家感到头痛。Russell和Quine把它们整理出来,说它们实际上不是“指涉的”,也就是说,认为上面的例子是用来指实体的是错误的。理解“爱丁堡自1999年以来一直是苏格兰的首都”的正确方法是说
苏格兰自1999年以来就有了首都,那就是爱丁堡。
这个句子不能变成一个疯狂的句子。问题解决了!奎因的观点是,自然语言是混乱的,或至少是复杂的,因为它是为了方便实际使用而设计的,但哲学家和逻辑学家应该通过正确的方式理解它们,从而使它们变得清晰。参考透明度是一种工具,用于带来这种意义的清晰度。
What does all this have to do with programming? Not very much, actually. As we said, referential transparency is a tool to be used in understanding language, i.e., in assigning meaning. Christopher Strachey, who founded the field of programming language semantics, used it in his study of meaning. His foundational paper "Fundamental concepts in programming languages" is available on the web. It is a beautiful paper and everybody can read and understand it. So, please do so. You will be much enlightened. He introduces the term "referential transparency" in this paragraph:
One of the most useful properties of expressions is that called by Quine referential transparency. In essence this means that if we wish to find the value of an expression which contains a sub-expression, the only thing we need to know about the sub-expression is its value. Any other features of the sub-expression, such as its internal structure, the number and nature of its components, the order in which they are evaluated or the colour of the ink in which they are written, are irrelevant to the value of the main expression.
The use of "in essence" suggests that Strachey is paraphrasing it in order to explain it in simple terms. Functional programmers seem to understand this paragraph in their own way. There are 9 other occurrences of "referential transparency" in the paper, but they don't seem to bother about any of the others. In fact, the whole paper of Strachey is devoted to explaining the meaning of imperative programming languages. But, today, functional programmers claim that imperative programming languages are not referentially transparent. Strachey would be turning in his grave.
We can salvage the situation. We said that natural language is "messy, or at least complicated" because it is made to be convenient for practical use. Programming languages are the same way. They are "messy, or at least complicated" because they are made to be convenient for practical use. That does not mean that they need to confuse us. They just have to be understood the right way, using a meta language that is referentially transparent so that we have clarity of meaning. In the paper I cited, Strachey does exactly that. He explains the meaning of imperative programming languages by breaking them down into elementary concepts, never losing clarity anywhere. An important part of his analysis is to point out that expressions in programming languages have two kinds of "values", called l-values and r-values. Before Strachey's paper, this was not understood and confusion reigned supreme. Today, the definition of C mentions it routinely and every C programmer understands the distinction. (Whether the programmers in other languages understand it equally well is hard to say.)
Both Quine and Strachey were concerned with the meaning of language constructions that involve some form of context-dependence. For example, our example "Edinburgh has been the capital of Scotland since 1999" signifies the fact that "capital of Scotland" depends on the time at which it is being considered. Such context-dependence is a reality, both in natural languages and programming languages. Even in functional programming, free and bound variables are to be interpreted with respect to the context in which they appear in. Context dependence of any kind blocks referential transparency in some way or the other. If you try to understand the meaning of terms without regard to the contexts they depend on, you would again end up with confusion. Quine was concerned with the meaning of modal logic. He held that modal logic was referentially opaque and it should be cleaned up by translating it into a referentially transparent framework (e.g., by regarding necessity as provability). He largely lost this debate. Logicians and philosophers alike found Kripke's possible world semantics to be perfectly adequate. Similar situation also reigns with imperative programming. State-dependence explained by Strachey and store-dependence explained by Reynolds (in a manner similar to Kripke's possible world semantics) are perfectly adequate. Functional programmers don't know much of this research. Their ideas on referential transparency are to be taken with a large grain of salt.
[Additional note: The examples above illustrate that a simple phrase such as "capital of Scotland" has multiple levels of meaning. At one level, we might be talking about the capital at the current time. At another level, we might talking about all possible capitals that Scotland might have had through the course of time. We can "zoom into" a particular context and "zoom out" to span all contexts quite easily in normal practice. The efficiency of natural language makes use of our ability to do so. Imperative programming languages are efficient in very much the same way. We can use a variable x on the right hand side of an assignment (the r-value) to talk about its value in a particular state. Or, we might talk about its l-value which spans all states. People are rarely confused by such things. However, they may or may not be able to precisely explain all the layers of meaning inherent in language constructs. All such layers of meaning are not necessarily 'obvious' and it is a matter of science to study them properly. However, the inarticulacy of ordinary people to explain such layered meanings doesn't imply that they are confused about them.]
下面的一个单独的“后记”将这个讨论与函数式编程和命令式编程的关注点联系起来。
[这是我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值和其他填充命令式程序员概念宇宙的复杂对象之间的区别,任何关于“引用透明性”的讨论从根本上都是错误的。
推荐文章
- 我如何用groupBy计算发生的事件?
- foreach和map有区别吗?
- 在函数式编程中,什么是函子?
- PHP中接口的意义是什么?
- 面向对象编程,函数式编程,过程式编程
- 什么是“P=NP?”,为什么这是一个如此著名的问题?
- 为什么不可变性在JavaScript中如此重要(或需要)?
- 如何使用underscore.js作为模板引擎?
- Scala中的“提升”是什么?
- Javascript相当于Python的zip函数
- 使用array_map()访问第一级键,而不调用' array_keys() '
- functools partial是怎么做的呢?
- 过程式编程和函数式编程的区别是什么?
- 没有可变状态,你怎么能做任何有用的事情?
- 如何在Python中使用lambda排序