4 ms·
Do you have sources for your definition? The original definition that I'm finding from Quine seems to broadly support the interpretation that an expression is r
by norir 3y ago
Do you have sources for your definition? The original definition that I'm finding from Quine seems to broadly support the interpretation that an expression is referentially transparent if it can be replaced by its value without altering program semantics, as others have stated. Regardless, it isn't clear to me how macros are any more or less referentially transparent than function calls in an impure language.
- whateveracct 3y agoI'm very sure the commenter is being a little pedantic But even pedantry can't argue that Java is a fundamentally more referentially transparent language than Haskell lol. That threw me for a loop.
- pron 3y agoRight, the incorrect and quite pointless common use of "referential transparency" in FP fan circles tends to throw people off when they first see and understand the actual meaning of the term.
- whateveracct 3y agoWell it's not pointless. The term as used in FP has a pretty well-defined meaning [1] and it is a quality only some programs have. And a program having that quality enhances (fast-and-loose) equational reasoning. [1] I can point at most Java code and prove how it fails the definition. It's not especially hand-wavey.
- pron 3y agoThe thing that is preserved is "meaning" or "referent" -- the term Quine uses (hence, "reference transparency") -- not "value". The distinction between referent/meaning and value is the most important aspect of distinguishing between pure FP programming languages and others, and yet that's the thing that is so commonly confused by FPers using the terminology, which makes it quite pointless. In most programming languages the reference or meaning of a term is not a value; in pure functional languages the meaning is a value and that's what makes them special, not their referential transparency which they share with imperative languages. Here's an example from C: int global_x = 0; void f() { x++; } void g() { x++; } f and g have the same meaning in C (but the function `void h() { x += 2; }` does not) yet `m(f)` and `m(g)` will not have the same meaning if M is defined as: #define m(x) #x However, f and g are interchangeable anywhere else (this is not actually true because their addresses can be obtained and compared; showing that a C-like language retains its referential transparency despite the existence of so-called l-values was the point of what I think is the first paper to introduce the notion referential transparency to the study of programming languages: https://github.com/papers-we-love/papers-we-love/blob/main/languages-theory/fundamental-concepts-in-programming-languages.pdf https://github.com/papers-we-love/papers-we-love/blob/main/l... You may be surprised to see that Strachey also uses the word "value" but his point later is that value is not what you think it is)
- norir 3y agoThank you. That response was clarifying. I understand now what you mean. Funnily enough though, the paper you cited begins: "Any discussion on the foundations of computing runs into severe problems right at the start. The difficulty is that although we all use words such as ‘name’, ‘value’, ‘program’, ‘expression’ or ‘command’ which we think we understand, it often turns out on closer investigation that in point of fact we all mean different things by these words, so that communication is at best precarious." Rather than debating the semantics of the colloquial usage of referential transparency, I'm more interested in the question: what can I tell at the call site of a function without knowing the definition of the function? In an impure language, I cannot tell whether the call has side effects without looking at the definition. This is true whether I am using a macro or simply a regular function call. Now, even if my language of choice is impure, referential transparency of expressions is still a useful concept that can inform how I write my program. I can use naming, for example, to suggest whether a function call may have side effects even if the language compiler can't verify the property. Not perfect, but better than nothing. And if I'm really confused by a bug, I can always just assume that the name is misleading and the function may have unintentional side effects. In other words, I can use the concept of referential transparency to implement a metaprogramming system in my head.