Java is Pass-By-Value, Dammit!
Quite possibly the most important article I’ve ever read, because it finally, finally explains to me what Java’s object-passing model is really all about. I’ve never understood it, and now I do: it’s exactly backwards from pass-by-reference, so it’s exactly backwards from the languages with which I grew up. The Object (and derivative) variables are pointers, not references, and calling them references only confuses people who grew up writing C (as I did).
Even more oddly, it explains to me what I’ve never quite understood about Python’s object model, because Python’s object model is exactly the same. Reproducing the code in the article above in Python creates the same result:
class Foo(object):
def __init__(self, x): self._result = x
def _get_foo(self): return self._result
def _set_foo(self, x): self._result = x
result = property(_get_foo, _set_foo)
def twid(y):
y.result = 7
def twid2(y):
y = Foo(7)
r = Foo(4)
print r.result # Should be 4
twid(r)
print r.result # Should be 7
r = Foo(5)
print r.result # Should be 5
twid2(r)
print r.result # Still 5
This demonstrates that Python’s code remains pass-by-value, with pythonic “references” in fact being pointers-to-objects. In the case of twid2, we change what the pointer y, which exists in the frame of the call twid2, points to and create a new object that is thrown away at the end of the call. The object to which y pointed when called is left unmolested.
This is important because it changes (it might even disrupt) the way I think about Python. For a long time, I’ve been using python calls out of habit, just knowing that sometimes objects are changed and sometimes they aren’t. Now that the difference has been made clear to me, in language that I’ve understood since university, either I’m going to be struggling for a while incorporating this new understanding, or I’m going to be much more productive.
This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com
no subject
Date: 2009-12-07 05:32 pm (UTC)Reconstructing the thoughts of some dude at Sun back in the nineties:
no subject
Date: 2009-12-07 05:40 pm (UTC)I don't think this is so much about the way Sun thinks (after all, Python was doing this years before Java came about) as it is about language confusion. References have always been confusing in C++, but their utility was so much better understood than the lossiness of pointers. Calling their "this thing refers to that thing right now, but if you use this thing as an lvalue for some other thing, this thing will refer to that other thing" a reference doesn't seem a stretch.
no subject
Date: 2009-12-07 10:05 pm (UTC)no subject
Date: 2009-12-07 10:08 pm (UTC)no subject
Date: 2009-12-07 10:32 pm (UTC)It was also written Literate, which may have something to do with my not getting lost while writing it.
no subject
Date: 2009-12-07 10:27 pm (UTC)Thanks, Larry Wall!
no subject
Date: 2009-12-07 10:24 pm (UTC)That's not true either, though I agree with the statement in the article you reference:
Objects are not passed by reference. A correct statement would be: "Object references are passed by value."
The problem is that Sun won the language war around the word "reference". So what distinguishes a "reference" from a "pointer" (no pointer arithmetic, no explicit dereferencing) no longer has anything to do with what distinguishes "pass-by-reference" from "pass-by-value".
I actually agree with the Java / Python way of doing things in this case, where more than one variable can refer to the same object, but two variables are never secretly the same variable. Although, that design decision works better in Python than in Java, since Python allows functions to have (effectively) multiple return values. (And even better in Lisp which has that plus macros.)