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.

Pure functions are required to
construct pure expressions. [...] Pure
expressions are often referred to as
being referentially transparent.

I find these statements confusing. If the side effects from a so-called "impure function" are insignificant enough to allow not performing them (i.e. replace a call to such a function with its value) without materially changing the program, it's the same as if it were pure in the first place, isn't it?

Is there a simpler way to understand the differences between a pure expression and a referentially transparent one, if any? If there is a difference, an example expression that clearly demonstrates it would be appreciated.

5 Answers
5

If I gather in one place any three theorists of my acquaintance, at least two of them disagree on the meaning of the term "referential transparency." And when I was a young student, a mentor of mine gave me a paper explaining that even if you consider only the professional literature, the phrase "referentially transparent" is used to mean at least three different things. (Unfortunately that paper is somewhere in a box of reprints that have yet to be scanned. I searched Google Scholar for it but I had no success.)

I cannot inform you, but I can advise you to give up: Because even the tiny cadre of pointy-headed language theorists can't agree on what it means, the term "referentially transparent" is not useful. So don't use it.

P.S. On any topic to do with the semantics of programming languages, Wikipedia is unreliable. I have given up trying to fix it; the Wikipedian process seems to regard change and popular voting over stability and accuracy.

Thanks. Can I infer that one of those three definitions is synonymous with "pure"?
–
AniFeb 11 '11 at 9:59

4

Well said! I might in fact note that Wikipedia itself labels both the articles cited as unreliable since they don't cite their sources. Debating the content of these articles is an exercise in futility.
–
Uday ReddyMar 23 '12 at 21:23

Your answer is three years old, maybe the paper you mention is accessible already. Can you give us the paper's name?
–
vinipsmakerOct 8 '14 at 7:51

All pure functions are necessarily referentially transparent. Since, by definition, they cannot access anything other than what they are passed, their result must be fully determined by their arguments.

However, it is possible to have referentially transparent functions which are not pure. I can write a function which is given an int i, then generates a random number r, subtracts r from itself and places it in s, then returns i - s. Clearly this function is impure, because it is generating random numbers. However, it is referentially transparent. In this case, the example is silly and contrived. However, in, e.g., Haskell, the id function is of type a - > a whereas my stupidId function would be of type a -> IO a indicating that it makes use of side effects. When a programmer can guarantee through means of an external proof that their function is actually referentially transparent, then they can use unsafePerformIO to strip the IO back away from the type.

So you're saying int func(int i) { int r = rand(); int s = r - r; return i - s; } is referentially transparent but not pure, because it "it is generating random numbers"? Why is it nor pure? It always returns the same result for the same argument, and does cause any observable side effects. On the other hand, if the call to rand()did have side-effects (let's say it changed the state of a global random number generator), it is neither pure nor referentially transparent. (Apologies if I completely misunderstood your post.)
–
AniFeb 2 '11 at 15:11

1

@Ani The issue isn't "observable" side effects -- it is side effects full stop. If I want to provide a mathematical model for my stupidId function, I need some notion of a global random generator -- i.e. I can't represent it without having a model that includes things outside of its arguments. Given that model, I can then demonstrate that it is referentially transparent -- which is a property of determined by the behavior of a function, rather than by the nature of its definition.
–
sclvFeb 2 '11 at 15:38

2

But it's not referentially transparent if it changes the state of a global random generator - replacing the function-call (at a call-site) with its value gives you a different program. No?
–
AniFeb 2 '11 at 15:43

@Ani -- In this case, arguably yes. But the example could also just read a byte out of a memory location accessible to other programs, off a port, out of a file, etc.
–
sclvFeb 2 '11 at 16:01

I'm somewhat unsure of the answer I give here, but surely somebody will point us in some direction. :-)

"Purity" is generally considered to mean "lack of side-effects". An expression is said to be pure if its evaluation lacks side-effects. What's a side-effect then? In a purely functional language, side-effect is anything that doesn't go by the simple beta-rule (the rule that to evaluate function application is the same as to substitute actual parameter for all free occurrences of the formal parameter).

For example, in a functional language with linear (or uniqueness, this distinction shouldn't bother at this moment) types some (controlled) mutation is allowed.

So I guess we have sorted out what "purity" and "side-effects" might be.

Referential transparency (according to the Wikipedia article you cited) means that variable can be replaced by the expression it denotes (abbreviates, stands for) without changing the meaning of the program at hand (btw, this is also a hard question to tackle, and I won't attempt to do so here). So, "purity" and "referential transparency" are indeed different things: "purity" is a property of some expression roughly means "doesn't produce side-effects when executed" whereas "referential transparency" is a property relating variable and expression that it stands for and means "variable can be replaced with what it denotes".

I realised that I've covered the "purity vs referential transparency" part of your question but utterly failed to find examples (say, a referentially transparent expression that is not pure). Sorry. But, I'm now in doubt whether it's technically correct to say that an expression is "referentially transparent".
–
Artyom ShalkhakovFeb 2 '11 at 4:58

This was one of my first thoughts, but I don't think it is correct. Wiki says "An expression is said to be referentially transparent if it can be replaced with its value." en.wikipedia.org/wiki/… Any thoughts? I do agree that I normally hear "pure function" and "r.t. expression".
–
AniFeb 2 '11 at 5:22

1

Yes, that (and foldoc.org/referential+transparency) addresses my doubt, thank you. So it seems that referentially transparent expression is the one that is also pure and is about substituting equals for equals (if A is equivalent to B and both are referentially transparent, then you can substitute some, but not all occurrences of A with B in some other expression and still the results will be the same).
–
Artyom ShalkhakovFeb 2 '11 at 6:04

A language is referentially transparent if (a)
every subexpression can be replaced by any other
that’s equal to it in value and (b) all occurrences of
an expression within a given context yield the
same value.

You can have, for instance, a function that logs its computation to the program standard output (so, it won't be a pure function), but you can replace calls for this function by a similar function that doesn't log its computation. Therefore, this function have the referential transparency property. But... the above definition is about languages, not expressions, as the slides emphasize.

[...] it's the same as if it were pure in the first place, isn't it?

From the definitions we have, no, it is not.

Is there a simpler way to understand the differences between a pure expression and a referentially transparent one, if any?

I'll quote what John Mitchell wrote in his book Concept in programming language. I don't remember it line by line but he defines pure functional language has to pass declarative language test which is:

"Within the scope of specific deceleration of x1,...,xn , all occurrence of an expression e containing only variables x1,...,xn have the same value."

In short as everybody else mentioned free from side-effects or no side effects ("Lack" of side effects).

In linguistics a name or noun phrase is considered referentially transparent if it may be replaced with the another noun phrase with same referent without changing the meaning of the sentence it contains.

Which in 1st case holds but in 2nd case it gets too weird.

Case 1:
"I saw Walter get into his new car."

And if Walter own a Centro then we could replace that in the given sentence as:

"I saw Walter get into his Centro"

Contrary to first :

Case #2 : He was called William Rufus because of his read beard.

Rufus means somewhat red and reference was to William IV of England.

"He was called William IV because of his read beard." looks too awkward.

Traditional way to say is, a language is referentially transparent if we may replace one expression with another of equal value anywhere in the program without changing the meaning of the program.

So, referential transparency is a property of pure functional language.
And if your program is free from side effects then this property will hold.

So give it up is awesome advice but get it on might also look good in this context.

And by the way imperative languages can also be referential transparent if we consider " variable say x refers to its location in memory". As replacing one variable with the another that names the same memory location will't change the meaning of program. hence referential transparency holds.
–
PushpaDec 5 '14 at 17:52

But we generally consider a variable say x refers as to the value stored in that location, which will't hold as referential transparent.
–
PushpaDec 5 '14 at 17:53