|
Referential transparency is a property of parts of computer programs. An expression is said to be referentially transparent if it can be replaced with its value without changing the program (in other words, yielding a program that has the same effects and output on the same input). The opposite term is referentially opaque. Since referential transparency involves the concept of determinacy (producing the same result for each input), all referentially transparent functions are determinate. An expression in a programming language is a combination of values and functions or procedures, interpreted according to the particular rules of precedence and of association for a particular programming language, which computes and then returns another value. ...
In philosophy, mathematics, and logic, a property is an attribute of an object; thus a red object is said to have the property of redness. ...
If all functions involved in the expression are pure functions, then the expression is referentially transparent. Also, some impure functions can be included in the expression if their values are discarded and their side-effects are insignificant. In computer programming, a function may be described as pure if both these statements about the function hold. ...
Referential transparency is one of the principles of functional programming; only referentially transparent functions can be memoized (transformed into equivalent functions which cache results). Some programming languages provide means to guarantee referential transparency. Functional programming is a programming paradigm that conceives computation as the evaluation of mathematical functions and avoids state and mutable data. ...
Memoization is a technique used to speed up computer programs by storing the results of functions for later reuse, rather than recomputing them. ...
A programming language is an artificial language that can be used to control the behavior of a machine, particularly a computer. ...
Examples and counterexamples
Arithmetic operations are referentially transparent: 5*5 can be replaced by 25, for instance. Many functions, particularly most of those in the mathematical sense, are referentially transparent: sin(x) is transparent, since it will always give the same result for any given x. The C++ expression x++; is not transparent, as it changes the value of x. However, the function int incr(int x) {return x+1;} is transparent. In most languages, print( "Hello world" ) is not transparent, as replacing it by its value (say, 0) changes the behavior of the program, as "Hello world" isn't printed.
today() is not transparent, as if you evaluate it and replace it by its value (say, "Jan 1, 2001"), you don't get the same result as you will if you run it tomorrow.
Contrast to imperative programming If the substitution of an expression with its value is valid only at a certain point in the execution of the program, then the expression is not referentially transparent. The definition and ordering of these sequence points are the theoretical foundation of imperative programming, and part of the semantics of an imperative programming language. In C LANGUAGE A sequence point is any point in a programs execution wherein all side effects of previous evaluations are complete and no side effects of subsequent evaluations have stored. ...
In computer science, imperative programming, as opposed to declarative programming, is a programming paradigm that describes computation in terms of a program state and statements that change the program state. ...
However, because a referentially transparent expression can be evaluated at any time, it is not necessary to define sequence points nor any guarantee of the order of evaluation at all. Programming done without these considerations is called purely functional programming. Purely functional is a term in computing used to describe algorithms, data structures or programming languages that exclude destructive modifications (updates). ...
The chief advantage of writing code in a referentially transparent style is that given an intelligent compiler, static code analysis is easier and better code-improving transformations are possible automatically. For example, when programming in C, there will be a performance penality for including a call to an expensive function inside a loop, even if the function call could be moved outside of the loop without changing the results of the program. The programmer would be forced to perform manual code motion of the call, possibly at the expense of source code readability. However, if the compiler is able to determine that the function call is referentially transparent, it can perform this transformation automatically. Static analysis is the term applied to the analysis of computer software that is performed without actually executing programs built from that software (analysis performed on executing programs is known as dynamic analysis). ...
Compiler optimization is the process of tuning the output of a compiler to minimize some attribute (or maximize the efficiency) of an executable program. ...
The primary disadvantage of languages which enforce referential transparency is that it makes the expression of operations that naturally fit a sequence-of-steps imperative programing style more awkward and less concise. Such languages often incorporate mechanisms to make these tasks easier while retaining the purely functional quality of the language, such as definite clause grammars and monads. A definite clause grammar (DCG) is a way of expressing grammatical relationships. ...
Wikibooks Haskell has a page on the topic of Understanding monads Some functional programming languages make use of monads[1] [2] to structure programs which include operations that must be executed in a specific order. ...
While in mathematics all function applications are referentially transparent, in programming this is not always the case. For example, take a function that takes no parameters and returns input from the keyboard. A call to this function might be GetInput(). The return value of GetInput() depends on what the user types in, so multiple calls to GetInput() with identical parameters (the empty list) may return different results. Euclid, Greek mathematician, 3rd century BC, as imagined by by Raphael in this detail from The School of Athens. ...
See: transparency (optics) alpha compositing GIF#Transparency transparency (overhead projector) market transparency transparency (telecommunication) transparency (computing) For X11 pseudo-transparency, see pseudo-transparency. ...
A computer keyboard is a peripheral partially modeled after the typewriter keyboard. ...
A more subtle example is that of a function that uses a global variable (or a dynamically scoped variable, or a lexical closure) to help it compute its results. Since this variable is not passed as a parameter but can be altered, the results of subsequent calls to the function can differ even if the parameters are identical. (In pure functional programming, assignment is not allowed; thus a function that uses global (or dynamically scoped) variables is still referentially transparent, since these variables cannot change.) In computer programming, a global variable is a variable that is accessible in every scope. ...
In computer programming in general, a scope is an enclosing context. ...
In programming languages, a closure is a function that refers to free variables in its lexical context. ...
Functional programming is a programming paradigm that conceives computation as the evaluation of mathematical functions and avoids state and mutable data. ...
The importance of referential transparency is that it allows a programmer (or compiler) to reason about program behavior. This can help in proving correctness, finding bugs that could not be found through testing, simplifying an algorithm, assisting in modifying code without breaking it, or optimizing code by means of memoization, common subexpression elimination or parallelization. A programmer or software developer is someone who programs computers, that is, one who writes computer software. ...
A diagram of the operation of a typical multi-language, multi-target compiler. ...
In theoretical computer science, correctness of an algorithm is asserted when it is said that the algorithm is correct with respect to a specification. ...
In mathematics, computing, linguistics, and related disciplines, an algorithm is a finite list of well-defined instructions for accomplishing some task that, given an initial state, will terminate in a defined end-state. ...
In computing, optimization is the process of modifying a system to make some aspect of it work more efficiently or use fewer resources. ...
Memoization is a technique used to speed up computer programs by storing the results of functions for later reuse, rather than recomputing them. ...
In compiler theory, common subexpression elimination (CSE) is the practice of finding repeated redundant expression evaluations, and replacing them with a single computation assigned to a temporary variable. ...
Parallel computing is the simultaneous execution of the same task (split up and specially adapted) on multiple processors in order to obtain results faster. ...
Some functional programming languages enforce referential transparency for all functions. Functional programming is a programming paradigm that conceives computation as the evaluation of mathematical functions and avoids state and mutable data. ...
With referential transparency, no difference is made or recognised between a reference to a thing and the corresponding thing itself. Without referential transparency, such difference can be easily made and utilized in programs.
Command-Query Separation principle -
Main article: Command-query separation The Eiffel method, although based on an imperative programming language, enforces a strict separation between commands, which can produce side effects, and queries, which must be referentially transparent: they return a result but do not change the environment. This rule is known as the Command-Query Separation principle and results in a style that clearly separates the referentially transparent parts. For example, in manipulating lists: Command-query separation (CQS) is a principle of object-oriented computer programming. ...
Eiffel is an object-oriented programming language which emphasizes the production of robust software. ...
Command-query separation (CQS) is a principle of object-oriented computer programming. ...
my_list.finish -- Move cursor to the end of the list value := my_list.item -- Get value at cursor position: referentially transparent This even affects such strongly imperative features as input: my_file.read_integer -- Get next integer; side effect, but no return value value := my_file.last_integer -- Get last integer read: referentially transparent Calling last_integer several times in a row is guaranteed to yield the same result each time.
Other example As an example, let's use two functions, one which is referentially opaque, and the other which is referentially transparent: globalValue = 0; integer function rq(integer x) begin globalValue = globalValue + 1; return x + globalValue; end integer function rt(integer x) begin return x + 1; end Now, rt is referentially transparent, which means that rt(x) = rt(x) as long as x is the same value. For instance, rt(6) = 6 + 1 = 7, rt(4) = 4 + 1 = 5, and so on. However, we can't say any such thing for rq because it uses a global value which it modifies. So, how is this a bad thing? Well let's say we want to do some reasoning about the following chunk of code: integer p = rq(x) + rq(y) * (rq(x) - rq(x)); Now, right off-hand, one would be tempted to simplify this line of code to: integer p = rq(x) + rq(y) * (0) = integer p = rq(x) + 0 = integer p = rq(x); However, this will not work for rq() because rq(x) does not equal rq(x)! Remember, that the return value of rq is based on a global value which isn't passed in and which gets modified all over the place. This goes against common sense since anything minus itself should be zero. This however will work for rt, because it is a referentially transparent function. Therefore we can reason about our code which will lead to more robust programs, the possibility of finding bugs that we couldn't hope to find by testing, and even the possibility of seeing opportunities for optimization. In computing, optimization is the process of modifying a system to make some aspect of it work more efficiently or use fewer resources. ...
See also |