views:

136

answers:

4

My understanding is that the term "referential transparency" can really only be applied to functional code. However, a method call on an object in object-oriented code can have a similar property, which is that the return value of the method, and the state of the object after a method call depends only on the state of the object before the call, and the method's arguments.

i.e. functional referential transparency:

i = foo(n, m);
// return value depends only on n, m

OO "referential transparency":

i = obj.foo(n, m);
// return value, and subsequent state of obj, depends 
// only on initial state of obj, n, m

Is there a name for this property?

If the state of obj does not change during the call to foo(), then the "object oriented" style is equivalent to the functional form if function overloading is supported since it could be rewritten as:

i = foo(obj, n, m);
// return value depends only on obj, n, m

However, is pretty common for the state of obj to change in a method call, so I'm not sure if this helps the analysis...

+1  A: 

the state of the object after a method call depends only on the state of the object before the call, and the method's arguments.

I suppose you could say that the method has no external dependencies.

Unlike referential transparency however, I'm not sure what this gains you. I suppose it means the method is easily testable.

AakashM
Yes, I was thinking about how this property helps with testing, and also how it helps one to reason about code.
mjs
Not sure I agree with the last statement - if one of the dependencies is the starting state of the object then it is very *hard* to test since enumerating all possible states for any non-trivial object makes selecting suitable test cases very difficult (I agree that having external dependencies makes the input space even bigger, to the point of combinatorial explosion)
Paolo
@Paolo agreed. However you will agree it's at least in principle at-all testable, unlike say a method which calls `DateTime.Now`
AakashM
@AakashM - Yes, that is true
Paolo
+3  A: 

The functional term would be referential transparency as you say. I would humbly propose that the form you've described here with the results depending on the method's arguments plus the object's state be termed referential opacity.

JUST MY correct OPINION
+3  A: 

I don't think that the property you described in the OO scenario gives you anything similar to what referential transparency does in functional programming. You described a property where the foo method modifies only the state of the obj object in the following call:

i = obj.foo(n, m); 

However, if you have another object that references obj then the call to foo also modifies the behavior of the other object. Since references between objects are essential in OO (meaning that this is a problem you cannot easily avoid), this means that the property you described doesn't tell you much about code. For example:

a = new Other(obj);
i = obj.foo(n, m);  // changes state of 'obj' and 'a'

If the foo method was referentially transparent (didn't modify any state - just returned some results), then that would be an interesting property - because it wouldn't modify the state of a.

Tomas Petricek
I appreciate your point that if the state of obj changes, then theoretically anything can happen when foo() is called since obj could have connections to any other object in the system, and I didn't consider this when posing the question. However, I think OOP "referential transparency" is still a meaningful and useful concept if the changes to obj are restricted to its own primitive or scalar types. This property makes it easier to test and reason about code, for example.
mjs
"then theoretically anything can happen when foo()" hits the nail on the head. Since this is true, it becomes much harder to be certain about the behavior of a program including a call to foo(). In practical terms, programmers must do more work to be sure that the modularity and safety of such an object. Further, it is often a global concern: You have to prefix your certainty with "Assuming the class is used as intended..."
MtnViewMark
+7  A: 

Your mistake is thinking that FP and OO are somehow fundamentally orthogonal. The "OO version" of referential transparency is just referential transparency.

An expression e is referentially transparent if and only if e can be replaced with its evaluated result without affecting the behavior of the program.

So if you have an expression o.foo(a), then it is referentially transparent if you could modify your code to replace it with the result of the call, without changing how your program behaves. Obviously, if o.foo is void, you can't do that. Ditto if it modifies the internal state of o. So the only way for o.foo(a) to be referentially transparent is if its result is a function of o and a.

In my mind, "functional code", is synonymous with "referentially transparent code".

Apocalisp
Additionally, if a) your program depends on the object identity of the result of `o.foo(a)`, or b) `o.foo(a)` has some side effect such as I/O, you can't replace the call.
retronym
I suppose it's fair to say that complete referential transparency is possible with OO code. (The standard getter will probably have this property.) But my main question is whether there's a name for the weaker but still useful property that following a method call, the return value and the final state of `o` itself are dependent only on the initial state of `o` and the method's arguments.
mjs
Standard getters are emphatically **not** referentially transparent. Referential transparency means that your results depend on passed-in parameters **only**. A getter **has** no passed-in parameter (unless you want to start talking about implied parameters like `this`/`self` in which case you're missing the point of the "transparent" part) and their returned value depends upon the state of the object involved in the call, an entity external to the function. Referential transparency is, basically, "you get what you see and nothing more". If there are unseen parts, that's not transparent.
JUST MY correct OPINION
If you can replace the call to the "getter" with its value, then it is RT, otherwise not. "Depends only on the initial state" is pretty weak. The initial state might depend on the entire universe.
Apocalisp
@Apocalisp: But you cannot replace the call to a getter with its value transparently. Its value depends on the state of the object it's called upon which can be changed by "spooky action at a distance" at any time. When you call the getter you do not know the state. (If you did there'd be no point in calling the getter, after all.) Every time you call the getter it can be something different so you can't just replace the call to the getter with its return value in future invocations. It is not referentially transparent.
JUST MY correct OPINION
You sometimes know the state. For example, if you just created that object on the previous line of your program.
Apocalisp