To say that because Python passes pointers-by-value under the hood (which is true for cpython, but not other implementations) is not useful. "Call by value" and "Call by reference" have reasonably precise definitions, and Python fits neither. See http://en.wikipedia.org/wiki/Call_by_sharing#Call_by_sharing for a discussion of the difference.
Re: call-by-sharing: "Although this term has widespread usage in the Python community, identical semantics in other languages such as Java and Visual Basic are often described as call-by-value, where the value is implied to be a reference to the object."
It's behaviorally call-by-value, where the value is always an object reference.
The difference is only mildly interesting, and the fervor with which you're arguing about it is wholly uninteresting, bordering on misleading. This is a semantic distinction with little to no use, and just serves to further confuse the rather simple and clear behavior.
afaik, this approach is from (or at least strongly championed at) comp.lang.python, and i would guess that their experience is that it is the most successful way of explaining python to new users there.
it's not so terrible - it works well enough for c.l.p, and anyone used to call by value with references/pointers is capable of working things out themselves.
really, it's largely a python (and c.l.p) cultural thing. you're berating some guy who's just a messenger for something that, in its context, doesn't do any harm (indeed, might help some newbies) (i don't have any skin in this game, but the guys on c.l.p do great work helping others; if this helps them it's fine by me).
You're right, it doesn't do any harm. But I think the way he's presenting it is harmful, as it's more confusing and not intended as explanation, but more as pointing out a distinction that isn't really present. He's very fervently defending a minor point of semantics, and I feel that's harmful.
Implementation details don't really matter: it's about how the language behaves (as is demonstrated by the SWAP litmus test). That implementations may do other things (generally for performance reasons, such as PyPy's function inlining) is irrelevant: those performance optimizations are not allowed to (noticeably) change semantics.
What do other Python implementations use? If it's something that indirectly keeps track of data location it's a pointer. The actual implementation of the pointer doesn't matter.
"Call-by-object-sharing" is better expressed as "call-by-object-pointer-value". But at this point it's just an argument over definitions. One either accepts that call-by-reference and call-by-value are the only two options along with the test above that includes C++, Ada, and Pascal as languages which support call-by-reference, or one doesn't.
One either accepts that call-by-reference and call-by-value are the only two options
I do not, there is also call by need and call by name. How does your test apply to Haskell? Incidentally call by sharing is much older than python. Wikipedia claims Liskov coined the term in 1974. I agree with you, call by value where the value happens to be a reference doesn't seem fundamentally different than call by value and probably doesn't need its own term.
To add to the historical point, Pascal was made in 1970 and supports both call-by-value and call-by-reference, so I get the feeling that Liskov was just muddying the waters. Considering that in modern usage call-by-sharing is relatively unheard of (sometimes even in Python circles), I really don't see what it has going for it.
Can Haskell pass the test? If it can't, it doesn't support call-by-reference.
You do bring up an interesting line of thought with call-by-need et al. I tend to just lump them under "lazy evaluation" and I don't really view them as impacting the value/reference dichotomy. The question there, then, is at the end of the day if/when an argument is evaluated (to whatever extent), does it match call-by-value or call-by-reference semantics? (And if the behavior is achieved with macro expansion, can it even rightfully be called a "call-by-X" behavior?) Clojure is adamantly call-by-value with its lazy evaluation, is there any particular reason why another language couldn't have the same lazy evaluation semantics as Clojure but support call-by-reference? pdw elsewhere in this thread suggests this whole "call-by-X" issue is pointless once you bring in lazy evaluation, I don't think that's a bad assessment.
The definition of call-by-value works fine for Python if you accept that object references are values in their own right, and that object variables contain those reference values.
If you don't accept that, then lots of other things become difficult to understand and explain as well. For instance, what do you call the thing that gets stored in a list? It's clearly not the object value itself, because that would preclude two lists from containing the same object.
Comments
To say that because Python passes pointers-by-value under the hood (which is true for cpython, but not other implementations) is not useful. "Call by value" and "Call by reference" have reasonably precise definitions, and Python fits neither. See http://en.wikipedia.org/wiki/Call_by_sharing#Call_by_sharing for a discussion of the difference.
Re: call-by-sharing: "Although this term has widespread usage in the Python community, identical semantics in other languages such as Java and Visual Basic are often described as call-by-value, where the value is implied to be a reference to the object."
It's behaviorally call-by-value, where the value is always an object reference.
The difference is only mildly interesting, and the fervor with which you're arguing about it is wholly uninteresting, bordering on misleading. This is a semantic distinction with little to no use, and just serves to further confuse the rather simple and clear behavior.
afaik, this approach is from (or at least strongly championed at) comp.lang.python, and i would guess that their experience is that it is the most successful way of explaining python to new users there.
it's not so terrible - it works well enough for c.l.p, and anyone used to call by value with references/pointers is capable of working things out themselves.
really, it's largely a python (and c.l.p) cultural thing. you're berating some guy who's just a messenger for something that, in its context, doesn't do any harm (indeed, might help some newbies) (i don't have any skin in this game, but the guys on c.l.p do great work helping others; if this helps them it's fine by me).
You're right, it doesn't do any harm. But I think the way he's presenting it is harmful, as it's more confusing and not intended as explanation, but more as pointing out a distinction that isn't really present. He's very fervently defending a minor point of semantics, and I feel that's harmful.
Implementation details don't really matter: it's about how the language behaves (as is demonstrated by the SWAP litmus test). That implementations may do other things (generally for performance reasons, such as PyPy's function inlining) is irrelevant: those performance optimizations are not allowed to (noticeably) change semantics.
What do other Python implementations use? If it's something that indirectly keeps track of data location it's a pointer. The actual implementation of the pointer doesn't matter.
"Call-by-object-sharing" is better expressed as "call-by-object-pointer-value". But at this point it's just an argument over definitions. One either accepts that call-by-reference and call-by-value are the only two options along with the test above that includes C++, Ada, and Pascal as languages which support call-by-reference, or one doesn't.
One either accepts that call-by-reference and call-by-value are the only two options
I do not, there is also call by need and call by name. How does your test apply to Haskell? Incidentally call by sharing is much older than python. Wikipedia claims Liskov coined the term in 1974. I agree with you, call by value where the value happens to be a reference doesn't seem fundamentally different than call by value and probably doesn't need its own term.
http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sha...
To add to the historical point, Pascal was made in 1970 and supports both call-by-value and call-by-reference, so I get the feeling that Liskov was just muddying the waters. Considering that in modern usage call-by-sharing is relatively unheard of (sometimes even in Python circles), I really don't see what it has going for it.
Can Haskell pass the test? If it can't, it doesn't support call-by-reference.
You do bring up an interesting line of thought with call-by-need et al. I tend to just lump them under "lazy evaluation" and I don't really view them as impacting the value/reference dichotomy. The question there, then, is at the end of the day if/when an argument is evaluated (to whatever extent), does it match call-by-value or call-by-reference semantics? (And if the behavior is achieved with macro expansion, can it even rightfully be called a "call-by-X" behavior?) Clojure is adamantly call-by-value with its lazy evaluation, is there any particular reason why another language couldn't have the same lazy evaluation semantics as Clojure but support call-by-reference? pdw elsewhere in this thread suggests this whole "call-by-X" issue is pointless once you bring in lazy evaluation, I don't think that's a bad assessment.
The definition of call-by-value works fine for Python if you accept that object references are values in their own right, and that object variables contain those reference values.
If you don't accept that, then lots of other things become difficult to understand and explain as well. For instance, what do you call the thing that gets stored in a list? It's clearly not the object value itself, because that would preclude two lists from containing the same object.