8 ms·
Java is pass-by-value, Dammit (and so are Ruby and Python, Dammit)
- araneae 17y agoI've heard that java is both pass-by-value and reference in one class, and then heard that it was pass-by-value only in another. The difference was that the first was at a university that primarily used java, and the second was at a university that primarily taught in C++. The fact is the usefulness of these concepts depend on what language you're writing in. In java, where pointers aren't explicit, you need to know when you're assigning a variable a memory locale versus a value. In C++, where pointer assignment is explicit, that's not a useful concept, so pass-by-reference has a different meaning. I honestly think we should come up with a different name for pass-by-reference the way it is used in C++. It's not like people actually write code using pass-by-reference anyway :D.
- deleted 17y ago[deleted]
- omnigoat 17y agoI do believe this is why my university teaches Java for one year, then C for the second, before you even get to glance at (C++|Python|Perl|C#|other). I'm a compiler-writer, and we don't need different names - they have well defined meanings. What we need is people to stop misusing them. You've done it yourself, because C doesn't have pass-by-reference. C++ does (ie, references...), but C does not. Stop doing it! Stop misusing those terms! You just read an article that actually spelled it out, and still misused them!
- raganwald 17y agoRedefining terms that have precise meanings into terms that have imprecise meanings based on vulgar precedent is a symptom of a pop culture. Cue Alan Kay quote in 3, 2, 1, ...
- ftl 17y ago"In the last 25 years or so, we actually got something like a pop culture, similar to what happened when television came on the scene and some of its inventors thought it would be a way of getting Shakespeare to the masses. But they forgot that you have to be more sophisticated and have more perspective to understand Shakespeare. What television was able to do was to capture people as they were. So I think the lack of a real computer science today, and the lack of real software engineering today, is partly due to this pop culture." Full conversation: http://queue.acm.org/detail.cfm?id=1039523 http://queue.acm.org/detail.cfm?id=1039523
- araneae 17y agoBlah blah blah. In Shakespeare's day, his plays were ribald entertainment for the masses. People are continuously complaining about how the old ways were better, and one is entitled to one's opinion, but the old ways are in the past and gone. Soon the last person who remembers them will be dead and there will be no one to complain about it, so what's the point?
- halo 17y agoWow, that's one of the most pretentious paragraphs I've ever read. I mean, let's use the exact same argument, swapping television for books: "In the last 25 years or so, we actually got something like a pop culture, similar to what happened when widespread literacy came on the scene and some of its perpetrators thought it would be a way of getting the Bible to the masses. But they forgot that you have to be more sophisticated and have more perspective to understand the Bible. What books were able to do was capture people as they were."
- deleted 17y ago[deleted]
- philwelch 17y agoExcept, historically that's absolutely wrong. Since the advent of printing, the Bible has been the most widely published book in the world because the masses, as they are, have historically been religious people.
- mattdawson 17y agoPython, for one, doesn't help to make the matter any clearer. In fact, Python makes it look like pass-by-reference is used, even when it isn't. For a better explanation than I could ever come up with: http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference/986145#986145 http://stackoverflow.com/questions/986006/python-how-do-i-pa... Just to play devil's advocate: if it looks like a duck and quacks like a duck, why would I call it anything other than "duck"? It may be technically correct to say that (in Python, at least) everything is passed by value. But if it helps someone remember that lists may be altered when passed to a function and that tuples can't, what's the real harm? Again: devil's advocate.
- olavk 17y agoIt is just the terminology that is confusing, because the word 'reference' has a different meaning when talking about parameter passing semantics, than when talking about references to objects. The Effbot suggest we call Python call semantics for 'call-by-object-reference' http://effbot.org/zone/call-by-object.htm http://effbot.org/zone/call-by-object.htm which makes it a lot clearer.
- scott_s 17y agoBecause it means they don't understand what's going on in the language runtime. That is, it betrays ignorance.
- enjo 17y agoI think it's really important to understand why tuples can't be modified and lists can. If you explain it away with something factually incorrect about pass-by-reference, your doing a real disservice to whomever you are teaching. After all, the issue here has nothing to do with parameter passing and everything to do with object design. It's important to understand that tuples are truly immutable and what the implications of that is. Misuse of tuples and lists are one of the biggest problems I see in novice (and often not so novice) python code. How often do you see someone copying tuples (often inadvertently) when list semantics are far more efficient? That stems from a fundamental misunderstanding of immutability, something that might stem from not understanding how parameters are truly passed in the language.
- rlpb 17y agoMeanings are only well-defined in their particular contexts.
- steveklabnik 17y agoIn this case, the context is "programming languages." The term has a very well-defined meaning for all lanugages.
- fauigerzigerk 17y agoI think the confusion results from the fact that people use the phrase "pass by reference" without ever explicitly stating what the referenced thing is. In the original sense of the phrase, I believe, that thing was the variable itself in the form of an alias, not the object/value that a pointer variable might be pointing to.
- diN0bot 17y agodef swap(a, b): t = a a = b b = t def swap2(a, b): t = a['v'] a['v'] = b['v'] b['v'] = t x = 3 y = 8 xx = {'v': x} yy = {'v': y} swap(x, y) # changes nothing swap(xx, yy) # changes nothing swap2(xx, yy) # changes 'v' values in xx and yy, but not x or y
- dustmop 17y agoHence the word "traditional" in the article.
- jganetsk 17y agoCan you write a traditional swap(a,b) method/function in the language? What about languages that are immutable by default, like Haskell, OCaml, and Erlang? You can't write a swap function. Therefore, are they pass-by-value? Actually, in OCaml, you can write the swap function. let swap a b = let temp = !a in a := !b; b := temp let x = ref 3 in let y = ref 8 in swap x y But now, you are passing references by value, as Java does. So maybe they are pass-by-value. But, when your language is immutable, pass-by-reference (whatever that would mean), doesn't effect the language semantics. They are pass-by-(it's-moot).
- jerf 17y agoI've really come to believe that all these terms should be explicitly understood to be domain specific. I can not think of a single term in common use that doesn't have edge cases and other such lacunae when it comes to application to real languages. You name the term, "object orientation", "functional", "reference" vs. "pointer", the distinction really only applies to a given language. Even the putative "true" definition is usually only the "true" definition in the context of machine language, and something like a true Lisp machine might still end up with no applicable definition for common terms. (Every time I say this, someone tries to correct me, but it is followed up by someone who then tries to debate the definition being used to correct me. It really is all relative.) So, in this case, the definition being given for "-by-value" vs. "-by-reference" does hold across a wide variety of imperative languages, but as you point out has no meaning in strictly-immutable functional languages since even inside a given function you can't write a "swap", let alone as a function. The terms only have meanings in certain contexts.
- eru 17y agoHaskell is something like pass-by-name. At least staff only gets evaluated at most once. But it's definitely not pass-by-value, since not everything gets evaluated down to a value.
- jganetsk 17y agoYour argument would get ensnared by that of the original post. If you take the description of Java's passing semantics, and s/object/thunk/ and s/primitive/unboxed value/, you get a perfect description of Haskell's passing semantics.
- jp_sc 17y agoActually in Python is pass-by-reference with lists and dictionaries.
- pwmanagerdied 17y agoLists and dictionary aren't special, and they aren't pass-by-reference in the sense referred to in the article. def foo(my_list): my_list = [ "my", "new", "list" ] Executing this function will not change the value of the list passed to it, it will create a new list and reference it locally. If calling foo(old_list) caused old_list to now contain [ "my", "new", "list" ], then it would be pass-by-reference in the sense this article refers to. EDIT: To clarify, you can mutate mutable arguments in-place, but you can't change what is being referred to by the identifiers used to refer to these arguments outside of the context of the function, which is what is meant by pass-by-reference in the article.
- eru 17y agoThough my_list.append("blub") does change the outside list. Does this matter?
- pwmanagerdied 17y agoIn Python you never deal with an object itself, just a reference to it, so you can change the value of any mutable object you pass to a function, lists and dictionaries are just a couple of examples of these. The problem (discussed by the article) is that "pass-by-reference" is a term that is used a couple of different ways. By someone's definition, this property of Python objects might cause them to consider the calls to pass-by-reference, but the way the author defined it in this article they are not.
- yason 17y agoYou are wrong. You can modify the original list in your example by having foo() call my_list.append("pwnd!"), for example. You can even use id() to verify that it really is the exactly same object that is visible to the caller and the callee. Python doesn't pass by reference (in the aliasing variables C++ sense) and it doesn't pass by value (in the functional sense) but rather, it passes references. Everything is an object anyway but objects aren't copied around. They're just bound or rebound to new variables. In the above example Python creates new local variables for all function arguments and binds them to the objects passed in as arguments. If those local variables are assigned to, they're just rebound to point to the new local object while the original variables in the caller code still remain bound to the original object.
- jancona 17y agoI think I first saw this debated in comp.lang.java in 1996: http://bit.ly/5XOSey http://bit.ly/5XOSey I don't think the arguments have changed much.
- eru 17y agoLong URL: http://groups.google.com/group/comp.lang.java/browse_thread/thread/8b6792bc5e5f87af/71f7ae8dbd7701fa?pli=1 http://groups.google.com/group/comp.lang.java/browse_thread/...
- dustmop 17y agoI reason I think this discussion is ever a problem is because in C++ "pass-by-value" has an extra meaning: that a deep copy occurs. There's no precise term for this, so people started (incorrectly) using "pass-by-reference" to talk about parameters that don't get deep copied. After all, in languages that do it right (Java, Ruby, Python, CL) there's only one parameter passing technique, and therefore no reason to make the distinction.
- bff 17y agoThere is a precise term for that and you said it - pass-by-value. Recall that somewhere each language turns into assembly and that in order to pass a value to a subroutine you must either place values into registers or push the data of the object you are passing onto the stack. Passing by value is desirable if you want to make sure that your local value is not modified. This gives the called function the freedom to modify it without worrying about side effects and without worrying about explicitly calling a copy constructor. Pass-by-reference comes from C++'s pass by reference, which is really just some sugar around passing a pointer by value and referencing it with the * operator in the function body (hence reference passing). I disagree that there is a right or wrong to this - C++ was made to be a generic programming language and thus gives many options to the programmer. If by "do it right" you meant "hide all options except the one most commonly used" okay. Otherwise I strongly disagree with that sentence especially because I use different kinds of "pass-by" whenever I program in C++ and will be using rvalue reference from the C++0x. Different languages suit different needs.
- dustmop 17y agoWell the term is not very precise if the way that you're using it and the way the article is using it are completely different. The article makes it clear that the term "pass-by-value" refers to the fact that the callers' references cannot be unseated by the function call; but it does not mean deep copies are made, like by copy constructor, hence that's why it applies to Java. Allow me to illustrate: vector<int> numbers; void f(vector<int> args); Due to C++'s copying, args[0] has a different address than numbers[0], because a deep copy of the vector was made. As the article states, this is not what pass-by-value is referring to, otherwise it would be false that Java / Python / Ruby et al are pass-by-value. So I disagree that the terms are clear, but rather that there is confusion around these terms. As for wanting immutability, it's almost always better for C++ code to write functions not like f but instead like this: void g(const vector<int>& args); And apologies for the editorializing, but I do consider this a language design flaw, one inherited from the backwards compatibility for C, which already allowed struct's to be passed (non-pointer) as args and then copied to keep the caller untouchable. It makes C++ code more verbose and more error prone, and is quite difficult for new programmers to grasp.
- cturner 17y agoOne set of English-language terms are being used by two communities. 1) Those of us who are language users care about use of the language from the perspective of the question, "If this thing gets passed in and I change it, does that change flow back to the calling method." Our perspective of pass-by-reference vs pass by value may originate from experiences learning C. We're probably wrong. 2) This guy is from the community of compiler people. He cares about implementation, and is probably correct. We need a spoken language abstraction that allows people to discuss the things they care about, and then be able to distinguish between them. The people in the position to cry 'get off my porch' are in the best position to point the rest of us is the right direction.
- dschobel 17y agoIt's not an academic point and he's not probably correct. If you don't understand that it's pass by value of references for non-primitives then you won't understand why your variable x is null after the method call: Object x = null; fooMe(x); //is x null or a Foo? [...] void fooMe(Object y){ y = new Foo(); } That's fundamental knowledge.
- ewjordan 17y agoIf you don't understand that it's pass by value of references for non-primitives then... Right: pass by value, of references. That's the complete answer, and it's really misleading to say anything else. I don't think any Java programmers actually have any misunderstanding here, even the worst of them know how this works. What's the problem? Also, the article tries to use code like this: void swap(SomeType& arg1, Sometype& arg2) { SomeType temp = arg1; arg1 = arg2; arg2 = temp; } to prove how different references in C++ are from Java. But the reason something like that might work in C++ is not that the semantics of parameter passing are different (references cannot be reseated in C++ any more than in Java), but that C++ uses the assignment operator to overwrite the contents of the lhs, and invokes the copy constructor automatically. The true equivalent code in Java works just fine, assuming the copy constructor and set method do the right things (which is a potential pitfall in C++, as well): static public void swap(SomeType arg1, SomeType arg2) { SomeType temp = new SomeType(arg1); arg1.set(arg2); arg2.set(temp); }
- dschobel 17y agoWhen I was interviewing java devs of all levels few (less than 10%, I'd say) could flat out say "it's pass by value for everything, for non-primitives you're passing references by value" but a lot more (roughly half) could trace the following code correctly. Object x = null; makeString (x); System.out.println (x); void makeString (Object y) { y = "This is a string"; } Maybe it's just a disconnect between theory and practice?
- moss 17y agoThis. Java sets up an environment where the parameter passing behavior just isn't surprising. If you've been programming in Java for a little while, it's very easy to have an intuitive feel for how parameters will act, without having to go back to theoretical principles. Knowing about the theory behind pointers, pass-by-value, and pass-by-reference will still make you a better programmer. But Java's a stronger language for not requiring that knowledge.
- kragen 17y agoYou're replying to a comment that says "interviewing java devs of all levels... a lot more (roughly half) could trace the following code correctly." That means that the other (roughly) half of the "Java devs" interviewed found Java's pass-by-value behavior to be surprising, even though there are no exceptions to it. So although Java's behavior is simple and consistent, the parent comment seems to flatly contradict your assertion, "If you've been programming in Java for a little while, it's very easy to have an intuitive feel for how parameters will act." It's also a perfect example of how programming in Java, or in fact any language with a parameter-passing mechanism and mutable variables, does require that knowledge, so your assertion that "Java's a stronger language for not requiring that knowledge" is nonsense.
- moss 17y agoYou're right: calling it "very easy" was overstating things to the point of absurdity. I do think Java's behavior has a big advantage in being easier to understand than the theory behind it is ("less than 10%"), but I had completely glossed over the "roughly half" point the first time I read this, and it really hurts my claim that Java's approach is trivial to understand. That said, I stand by "not requiring that knowledge". Java's behavior is understandable without having to know about value and reference semantics. That doesn't mean it doesn't require any knowledge. Specifically, I think it requires two points: (1) Variables are just names, so reassigning a variable doesn't change anything else in the system; (2) When you call a method on an object, you might change that object. In support of this: I've also been doing a lot of interviews recently. In my (admittedly limited) experience, the people who have had trouble with Java's parameter passing behavior are more experienced developers who've done a lot of work in other languages. Their confusion isn't from Java's behavior, it's the caution about pass-by-reference that they've brought over from C and C++. I don't really see junior people making this mistake. So I suspect having just a little knowledge of the value vs. reference issue makes Java harder to understand, by bringing up new and confusing possibilities. But, like I said, my experience is limited. If you do see new developers being confused by this aspect of Java (or Python, Ruby, or other languages with similar semantics), I'd be interested to hear about it.
- lg 17y agoa, b = b, a :)
- va_coder 17y agoThe user refractedthought at reddit had the best explanation IMO: Ok, I think the real losers in this discussion are the ones who fail to see both sides of the issue. We can cherry pick "refrence" definitions if we want, but really the nuts and bolts come down to this: Passing by value means that a copy of the parameter is made when the function is called and any changes to that variable will not be reflected outside of the function. Passing by reference means you pass a pointer to your data (and nothing more) so the function can dereference the parameter and affect data that exists outside of the function. All non-primitives in Java are implicit pointers, so when you pass one of these into a function, you are passing a pointer (or reference) to data that exists outside of the function. However, the reference itself, as it exists inside the function, can be changed to point toward something else. Essentially, the implicit pointer is passed by value, and that value can be altered without affecting anything outside the function. So technically yes, you could get away with calling this pass-by-value. However, the spirit of pass-by-reference is maintained for any part of the data that most people care about. The syntax is different from a pass-by-reference in C++, and there's a silly little trick you can do by changing the reference pointer (or silly trick you can't do by changing the pointer outside the function) but for all practical purposes you are doing the same thing. In my opinion, if you want to insist that Java strictly follows pass-by-value, then I think it has ceased to be a relevant distinction.
- scott_s 17y agodschobel's comment clearly demonstrates how the distinction between pass-by-value and pass-by-reference in Java is not purely academic: http://news.ycombinator.com/item?id=979799 http://news.ycombinator.com/item?id=979799 It's a relevant distinction because it's required to explain code behavior.
- rbanffy 17y ago"it has ceased to be a relevant distinction." I think this distinction ceased to be relevant in the late 70's...
- dkarl 17y agoSo technically yes, you could get away with calling this pass-by-value. However, the spirit of pass-by-reference is maintained for any part of the data that most people care about. And if there's any time you can afford to be loose about the spirit vs. the "technical" letter of the thing, it's when you're talking to a compiler. Right? I agree with the article. If you don't like the meaning of a technical term with a clear meaning, or if you simply don't have any occasion to use it properly, that's no excuse for repurposing it in the same context to mean something different that leads to confusion. It's worthwhile to remember that (true) pass by reference isn't just a curiosity from obsolete languages. It's common for people entirely new to programming to expect that function parameters might, or actually do, work that way. The terms are at least useful to explain things to new learners. In my opinion, if you want to insist that Java strictly follows pass-by-value, then I think it has ceased to be a relevant distinction. Even if you work only with pass by value languages, you should still respect the terminology. Some mathematicians only work with continuous functions, but they don't say, "Hey, this word 'continuous' would be a lot more useful if we redefined it to draw a useful distinction among the functions we actually work with." So "pass by reference" doesn't mean what you want it to mean and doesn't seem very useful to you. Invent your own terminology. Don't destroy existing terminology by sowing confusion. And that's all you can accomplish -- there are too many people walking around who already know what "pass by reference" means for you to get away with redefining it.
- 0wned 17y agoI think in C++... if you want to be sure the method/function does not alter the data globally and speed is not a concern, then pass by copy. If you want the method to alter the data globally, then pass by reference. If you want speed, but don't want alteration then pass by const reference.
- kentosi 17y agoI found this article rather surprising since I come from a primarily Java background. Do any other languages besides C++ allow this definition of pass-by-reference? The reason I ask is that it seems silly for me to change the way I talk just to satisfy one language that i don't even code in. And if so, when would it actually be practical to use this? The idea of reassigning a parameter in a function and then having that reassignment affect variables OUTSIDE the function sounds very strange to me (and possible even dangerous).
- Xixi 17y agoIt used to be very common in Turbo Pascal, where if I remember correctly you had to use the keyword ref.
- enjo 17y agoI disagree with the sentiment that you should simply ignore proper semantics because it's inconvenient. As the article points out, this stuff really does matter. There are classes of problems that these type of true reference semantics can be quite helpful. In C/C++ the technique is largely used in contexts where you want to return multiple values from a function, as there is no native support for dynamic tuples. Such is the way of statically typed languages. There are also cases where this type of reference to a pointer magic can really improve the efficiency of the algorithm. True reference passing is a tool. For those living in dynamic languages (as I do now), not a particularly relevant one. But that doesn't make the distinction any less important.