473,387 Members | 1,486 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Finding the instance reference of an object

Sorry for the numpty question ...

How do you find the reference name of an object?

So if i have this

bob = modulename.objectname()

how do i find that the name is 'bob'
Oct 16 '08
275 12001
On Nov 4, 2008, at 7:42 AM, Craig Allen wrote:
coming from C/C++ Python seemed to me call by reference, for the
pragmatic reason you said, modificaitons to function arguments do
affect the variable in the caller. The confusing part of this then
comes when immutable objects are passed in.
Yes, you stepped in the wrong direction right away and led yourself
into a morass of contradictions.

The correct way to look at it is that a Python reference is like a C++
pointer. C++ pointers are passed by value (unless you add & to
explicitly make a parameter by-reference), yet you can still use them
to mutate the objects they point to, right? Same thing in Python.
Nothing at all mysterious going on here. Compare this:

typedef Spam* SpamPtr; // (where Spam is some class)
// ...
void foo(SpamPtr spam)
{
spam->count = 4;
}

When you call foo, it modifies the spam object passed in, even though
the parameter is by-value. How? Because (looking more carefully),
you didn't actually pass in a Spam object; you passed in a POINTER TO
a Spam object. That pointer remained unchanged. You just used the
pointer to change some other data living on the heap. This is the
case exactly equivalent to Python:

def foo(spam):
spam.count = 4;

Same thing here; the variable you pass in is a reference to a Spam
object, and while that reference remains unchanged by the call, it is
used to change some other data that lives on the heap.

Here's a C++ example that has no analog in Python, because it uses
call-by-reference:

void throwOut(SpamPtr &spam)
{
printf("throwing out %s\n", spam->brand);
delete spam;
spam = nil;
}

Now here, when you invoke throwOut on a SpamPtr, your own SpamPtr
variable (the one that you pass in) actually gets set to nil. That's
because the formal parameter here is just an alias of the actual
parameter. You can't do that in Python; this attempt:

def throwOut(spam):
print "throwing out %s\n", spam.brand
spam = nil

would entirely fail to have any effect whatsoever on the Spam
reference you pass in. "spam" here is just a local variable within
the throwOut function, which has no connection to the variable passed
in other than it gets a copy of its value (i.e., it initially refers
to the same object as the actual parameter). This doesn't work, and
the C++ throwOut function has no analog in Python, because Python has
no call-by-reference.

Here's another C++ example that has no analog in Python, because it
passes an object directly on the stack rather than a reference to it:

void bar(Spam spam)
{
spam.count = 5;
}

This is the one that I know particularly confuses some users, because
it LOOKS like what you could do in Python, and has the same behavior
on the surface. But it's not analogous at all, because the "spam"
local variable here (and presumably the one in the calling context) is
an object stored directly on the stack, rather than a reference to an
object on the heap. Python can't do that (nor can Java, nor
REALbasic, etc.). This example is also call-by-value, but the value
in this case is a type that has no analog in Python. Python object
variables are references to objects on the heap, just like pointers in
C++ to objects created with "new". So this example is a red herring.

I'd be very interested in hearing whether, as a C/C++ user, the above
explanation is clear and makes sense to you.

Thanks,
- Joe
Nov 4 '08 #101
Joe Strout a écrit :
On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote:
>Maybe this is a surprise for you, because we haven't discussed this in
much detail in this group lately, but it applies to Python which does
call-by-object or call-by-sharing. ;-)

There's no such thing. Those are just terms made up by the Python
community
Did you read *any* of the many answers in this thread ? This term comes
from lisp, and existed years before Python.
to in place of the more standard "call-by-value" terminology
to make Python seem more mysterious than it really is.
Looks a bit paranoid to me.
Nov 4 '08 #102
On Tue, 04 Nov 2008 09:06:45 -0700, Joe Strout wrote:
This example is also call-by-value, but the value in this case is a type
that has no analog in Python.
I'm disappointed to see that my prediction that Joe would, yet again,
utterly ignore all the arguments against his pet theory was correct. It's
gratifying to be proven right, of course, but I'd prefer to be wrong and
reduce the amount of confusion and obfuscation that Joe is causing.

Over the years, I've had the misfortune to deal with many people like
Joe. They get a fixed idea in their head, and regardless of the facts
they will stick to it, no matter what: "when the facts disprove your pet
theory, ignore the facts".

When we're talking about the value of a variable in Python, why on earth
would you drag entities that do not exist in Python into the discussion?
That is too low a level. It's analogous to my earlier tongue-in-cheek
suggestion that all languages are in fact call-by-bit-flipping:
technically true at some level of explanation, but not at the level of
the Python virtual machine.

--
Steven
Nov 4 '08 #103
On Nov 4, 2008, at 3:42 PM, Steven D'Aprano wrote:
>This example is also call-by-value, but the value in this case is a
type
that has no analog in Python.

I'm disappointed to see that my prediction that Joe would, yet again,
utterly ignore all the arguments against his pet theory was correct.
I'm not doing that, but the folks on the other side are. (Well, I
don't know if you are in particular, as I've been deleting your
messages to save my blood pressure... this one caught my eye though,
alas.)

For example: we have arguments that you can "modify" a parameter
passed to a function in Python. These ignore the fact that you can
only use (dereference) that parameter to modify something else, no
different from a pointer passed by-value in C/C++. And, when a very
simple test for by-reference is brought up (i.e. writing a Swap
method), this gets ignored again and again, by the otherwise perfectly
nice fellow I've been discussing this with privately for days. There
are many other examples.

It boils down to this: Python's behavior is demonstrably the same as
any other modern OOP language, INCLUDING those that have both by-
reference and by-value parameter modes, except that in Python (as well
as Java), only the by-value mode is available.

This is easily shown, and I've done exactly that at <http://www.strout.net/info/coding/valref/
>.
But I predict that you'll ignore all this evidence that goes against
your pet theory, and continue to cause confusion and obfuscation on
the topic.
When we're talking about the value of a variable in Python, why on
earth
would you drag entities that do not exist in Python into the
discussion?
I don't, but others do, for example bringing up C structs or C++
objects on the stack, which don't exist in Python (Python objects live
on the heap, and all you have on the stack are references to them; the
proper C/C++ analogy is an object created with "new" and referenced
entirely via pointers).
That is too low a level. It's analogous to my earlier tongue-in-cheek
suggestion that all languages are in fact call-by-bit-flipping:
technically true at some level of explanation, but not at the level of
the Python virtual machine.
I agree that we don't need to talk about bits. But we do need to
understand whether code such as:

a = SomeClass()
b = a

creates two objects, or merely two references to the same object.
Once we know whether we're dealing with values or references, then
everything else becomes simple and clear, no matter what language
we're building in.

I know you really want Python to be unique and special -- and it is,
in many ways, but this isn't one of them. Python is an OOP language
whose variables contain references to objects, and where such
references are passed (by value) to methods, just like Java, and like
the default parameter mode in VB.NET, REALbasic, and C++ (though those
languages also offer a by-reference mode that Python and Java do not).

Your continued attempts to obfuscate this simple behavior does no
credit to you or Python.

Best,
- Joe

Nov 4 '08 #104
On Nov 4, 2008, at 3:54 PM, Steven D'Aprano wrote:
At the level of Python code, Python operates on *objects*. When you
call
a function with an argument, the argument (an object) is NOT copied,
it
is passed to the function. If you mutate the argument inside the
function, you are changing the object and the caller will see the
mutation: this is just like call-by-reference, and unlike call-by-
value.
And here is the key bit that you are missing.

When you pass a reference to an object to a function, and then mutate
the object, then OF COURSE the caller (as well as any other holders of
a reference to that object) will see the mutation. This is true in
ANY language. Pick your language, and I will demonstrate it. Here
are a few to get us started (assume a class "Person" with an attribute
"zipcode"):

C++:
void foo(PersonPtr who) {
who->zipcode = 12345;
}

Java:
void foo(Person who) {
who.zipcode = 12345;
}

REALbasic/VB.Net:
Sub foo(ByVal who as Person)
who.zipcode = 12345
End Sub

Python:
def foo(who):
who.zipcode = 12345
So please clarify your position by identifying which statement applies:

1. You don't believe that these languages are actually passing by value.
2. You don't believe these examples are mutating an object.
3. You don't believe these mutations can be seen by the caller after
the call.
4. You now see how a mutating an object within a function tells you
NOTHING about how the reference to that object was passed.
5. You see that the first three languages above are passing a
reference by value and using that to mutate and object, yet for
reasons still mysterious, the Python example (which has exactly the
same behavior) must be doing something different.

I hate being confrontational, but you're the one accusing me of
ignoring evidence against my "pet theory" (by which you mean the
standard definitions of c-b-v and c-b-r). Let's see what you do with
this evidence that directly contradicts yours.

Sigh.
But if you assign a different object to the argument name, the caller
does NOT see the change, which is just like call-by-value.
This at least you have correct.
So depending
on what type of object the argument is, and depending on what you do
inside the function, you get something that looks rather like call-by-
value or call-by-reference semantics.
But no, you don't, as I just demonstrated above (and explained a week
ago at <http://www.strout.net/info/coding/valref/>). You always have
call-by-value semantics. The semantics are exactly the same as in any
other language with anything resembling an object reference, including
those with both "ByVal" and "ByRef" modes (except that there is no
equivalent to the "ByRef" mode in Python).
But what the Python VM does is the
same no matter what you do: Python's calling model is different from
either byval or byref.
No, it's exactly byval. No. Different. In. Any. Way.

Let's tackle it this way: one of the following must be true for your
belief system to prop itself up at all:

1. Python's behavior is different from Java, REALbasic, VB.NET, and C++.
....or...
2. None of those languages mentioned use call-by-value.

In fact both of these statements are false, but we can cut our time
and effort in half if you will just select the one that you believe to
be true, so we can focus on that. Which is it?

Thanks,
- Joe

Nov 4 '08 #105
On Nov 4, 5:02*pm, Joe Strout <j...@strout.netwrote:
On Nov 4, 2008, at 3:42 PM, Steven D'Aprano wrote:
When we're talking about the value of a variable in Python, why on *
earth
would you drag entities that do not exist in Python into the *
discussion?

I don't, but others do, for example bringing up C structs or C++ *
objects on the stack, which don't exist in Python (Python objects live *
on the heap, and all you have on the stack are references to them; the *
I actually saw an implementation of Python once that did not have
references-to-objects on its stack. It kept them on the heap, and
kept references to those containers in another container. The second
container was a global variable, so that was on the stack at least.
This strongly seems to interfere with your analogy to C++'s c-b-v
mode.

On the other hand, you could say that VB.NET's c-b-v mode is not true
to C++'s c-b-v mode, in which case lots of people will just side with C
++.
Nov 5 '08 #106
On Tue, 04 Nov 2008 16:02:29 -0700, Joe Strout wrote:
On Nov 4, 2008, at 3:42 PM, Steven D'Aprano wrote:
>>This example is also call-by-value, but the value in this case is a
type
that has no analog in Python.

I'm disappointed to see that my prediction that Joe would, yet again,
utterly ignore all the arguments against his pet theory was correct.

I'm not doing that, but the folks on the other side are. (Well, I don't
know if you are in particular, as I've been deleting your messages to
save my blood pressure... this one caught my eye though, alas.)
Yeah, we are all wrong and you are right. Because you say so and ignore
messages that might have facts that are not good for your blood
pressure. Very convincing.
For example: we have arguments that you can "modify" a parameter passed
to a function in Python. These ignore the fact that you can only use
(dereference) that parameter to modify something else, no different from
a pointer passed by-value in C/C++.
But we have no pointers in Python. "Pointer" is a data type in C and C++
but Python, the language, has no such type.
It boils down to this: Python's behavior is demonstrably the same as any
other modern OOP language, INCLUDING those that have both by- reference
and by-value parameter modes, except that in Python (as well as Java),
only the by-value mode is available.
Guess what, I find call-by-value in Java for objects the wrong term too.
Same reason: Java has no pointer or reference as data type.
>When we're talking about the value of a variable in Python, why on
earth would you drag entities that do not exist in Python into the
discussion?

I don't, but others do, […]
You have said the value that is copied is a pointer to the object. So
the value in your call-by-value is something that doesn't exist in the
Python language.
I know you really want Python to be unique and special -- and it is, in
many ways, but this isn't one of them. Python is an OOP language whose
variables contain references to objects, and where such references are
passed (by value) to methods, just like Java, and like the default
parameter mode in VB.NET, REALbasic, and C++ (though those languages
also offer a by-reference mode that Python and Java do not).
That's just because you seem to insist that a "variable" is a name for a
memory location. A variable brings together name, type, memory location,
and a value, and in Python type and memory location are attached to the
value and not the name, like in C++ for example.
Your continued attempts to obfuscate this simple behavior does no credit
to you or Python.
I think explaining that the object is shared, or given another name
locally, is much simpler than to explain the underlying machinery two
levels below (because the CPython-VM doesn't know pointers either).
Maybe not for people who know that low levels from older languages and
insist on explaining everything in the terms of those. Maybe that's the
reason for the Java folks to call their strategy call-by-value, because
they were afraid to confuse C++ programmers with "new" concepts.

Ciao,
Marc 'BlackJack' Rintsch
Nov 5 '08 #107
On Nov 4, 6:02*pm, Joe Strout <j...@strout.netwrote:
I know you really want Python to be unique and special -- and it is, *
in many ways, but this isn't one of them. *Python is an OOP language *
whose variables contain references to objects, and where such *
references are passed (by value) to methods, just likeJava, and like *
the default parameter mode in VB.NET, REALbasic, and C++ (though those *
languages also offer a by-reference mode that Python andJavado not).
To Steve's defense, he doesn't claim that Python is special; in one
reply he also disputed the claim that even Java is call-by-value. Of
course most Java programmers would have a hard time taking this claim
seriously, but at least you both agree that Python and Java have the
same call semantics, you just disagree on the name. Googling for 'java
"call by sharing"' brings back only a few results with almost half of
them being Python-related discussions. Steve is definitely in the
minority but he's not completely alone: from
http://www.cs.princeton.edu/courses/...15/Lec15.html:

"""
Like most pure object-oriented languages, Java only supports by "call-
by-sharing". At the implementation level, this is the same as call-by-
value. I.e., the actual parameter value is copied into the formal
parameter before executing the body. At the end of the execution of
the body, the formal parameter just goes away - no copy back occurs. I
prefer to describe it as call-by-sharing because, while you may not
replace the value via an assignment in the method body, you may change
the state of an object value. In particular, if a parameter evaluates
to an object, one can send messages to it which can change its state.
"""

I believe the main source of confusion is wrt C/C++. The following
definition has different semantics in C++ and Java, although they are
both considered call by value:

void foo(Person who) {
who.zipcode = 12345;
}

In C++ a Person object itself is copied while in Java (and Python)
only the reference ("handler") is copied. By the way, passing a
(copied) reference is *not* equivalent to call by reference: in the
former case, the assignment of the reference to a different object has
only a local effect, i.e. it is not reflected to the caller's frame,
whine in call by ref it does.

George
Nov 5 '08 #108
On Tue, 04 Nov 2008 18:00:35 -0800, George Sakkis wrote:
On Nov 4, 6:02Â*pm, Joe Strout <j...@strout.netwrote:
>I know you really want Python to be unique and special -- and it is, in
many ways, but this isn't one of them. Â*Python is an OOP language whose
variables contain references to objects, and where such references are
passed (by value) to methods, just likeJava, and like the default
parameter mode in VB.NET, REALbasic, and C++ (though those languages
also offer a by-reference mode that Python andJavado not).

To Steve's defense, he doesn't claim that Python is special; in one
reply he also disputed the claim that even Java is call-by-value.

Python is as special as CLU, Lisp, Emerald, Iota and others.
"As in Java, the calling semantics are call-by-sharing: the formal
argument variable and the actual argument share the same value, at least
until the argument variable is assigned to. Assignments to the argument
variable do not affect the value passed; however, if the value passed was
an array, assignments to elements of that array will be visible from the
calling context as well, since it shares the same array object."

http://www.cs.cornell.edu/courses/cs...iota/iota.html

Of
course most Java programmers would have a hard time taking this claim
seriously,
That's their problem, not mine. If the Java community wishes to redefine
"value" to mean an arbitrary, implementation-dependent reference instead
of the actual value of the variable, that's their loss.
--
Steven
Nov 5 '08 #109
"Joe Strout" <jo*@strout.netwrote:

4. You now see how a mutating an object within a function tells you
NOTHING about how the reference to that object was passed.
5. You see that the first three languages above are passing a
reference by value and using that to mutate and object, yet for
reasons still mysterious, the Python example (which has exactly the
same behavior) must be doing something different.
This is dialectic nit picking - WTF makes "passing a reference by value"
different from "passing a reference" - the salient point is that its a reference
that is passed - would you expect another level of indirection - a reference to
the
reference, or what, before you admit that the thing that is passed is a
reference
and not a copied value of the OBJECT that is of interest.

Looks to me that even if there were ten levels of indirection you would still
insist that its a "pass by value" because in the end, its the actual memory
address of the first pointer in the queue that is passed. If that is what you
mean,
it is obviously trivially true - but then ALL calling can only be described as
"call by value" - which makes nonsense of what the CS people have been
doing all these years.

"Calling by value" is not a useful definition of Pythons behaviour.

- Hendrik

Nov 5 '08 #110
Dennis Lee Bieber wrote:
I'm sure all the programmers using FORTRAN for the last 50 years
will be very surprised to hear that it uses call-by-value!
That should be 'last 31 years'. Fortran IV *was* call-by-value, as
least for scalars. I remember spending a couple of hours tracking down
an obscure 'bug' in a once-working program when I ran it with F77. (I
had not noticed the call-by-reference switch.) The reason was, as I
remember, 'x = -x' in a function. I never forgot the difference.
I've used it for 30 years
Then you apparently missed the switch ;-).

tjr
Nov 5 '08 #111
Lie
On Nov 4, 9:33*am, Joe Strout <j...@strout.netwrote:
On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote:
Maybe this is a surprise for you, because we haven't discussed this in
much detail in this group lately, but it applies to Python which does
call-by-object or call-by-sharing. *;-)

There's no such thing. *Those are just terms made up by the Python *
community to in place of the more standard "call-by-value" terminology *
to make Python seem more mysterious than it really is. *I guess you *
can call it "purple bananas" if you want, but the behavior is exactly *
the same as what every other language calls call-by-value.

But I really am trying not to continue this debate. *So that's my last *
reply about it for tonight, I promise. *:)

Cheers,
- Joe
<http://www.strout.net/info/coding/valref/>
I'm fed up with you.

In Von Neumann Architecture computers, only pass-by-value is natively
supported. Other idioms are made on top of pass-by-value.

That's why exclusively pass-by-value languages like C is most flexible
than other exclusively pass-by-<insertanythinghere>.

BUT the difference is clear, if you want to do pass-by-reference in C
(I prefer to call it faux pass-by-reference), you'd have to manually
find a variable's address, pass it by-value, then dereference the
address. Compare with VB's ByRef or C++'s &, which does all that
_automatically_ for you behind the scene.

Another example: pass-by-object. I disagree with the term pass-by-
object-reference, since the notion of object reference is unnecessary
in a true pass-by-object mechanism (i.e. we should travel outside VNA
realm for a true pass-by-object mechanism). Problem is: I'm not aware
of any computer architecture that can accommodate pass-by-object
natively or whether such architecture is feasible to be made.
Solution: Emulate such architecture on a VNA computer. Limitations:
pass-by-object implementation on a VNA computer requires the notion of
object reference/pointer because VNA computers cannot pass object, it
can only pass numbers.

In pass-by-object, the whole object is passed around, not a copy of
the object like in pass-by-value or a copy of the pointer to the
object like in faux pass-by-reference. This makes pass-by-object
actually closer to pass-by-reference than to pass-by-value, since the
notion of VNA's requirement for Object Reference means passing
pointers around. But don't let it confuse you, the pass-by-object
mechanism itself does not recognize Object Reference, unlike pass-by-
reference recognition of reference/pointer.

Now that I have clearly defined the line between pass-by-object and
pass-by-value, I'm left with you thinking what's the difference
between pass-by-object and pass-by-reference. In pass-by-reference,
names are _mnemonic to location in memory_. In pass-by-object, names
are _mnemonic to objects_. In pass-by-reference, when we assign a
value to the name, we'd assign a value _to the location in memory_. In
pass-by-object, when we assign a value to the name, we assign an
object _to the name_. When passing parameters, pass-by-reference
systems passed the memory address and alias that memory address to a
local name. In pass-by-object system, since the object itself has no
idea of its own name, so it is rebound to a local name. You can say
that pass-by-reference system is memory-location-centered, while pass-
by-object system is name-centered.

To summarize, the key bit you're missing is built-in _automatic_
abstraction from pass-by-value. All pass-by-<insertanythingexcept
pass-by-value is an emulation over an architecture that can only
natively pass-by-value. pass-by-reference is emulated in C, C++, and
VB by passing memory address/pointer but C isn't a by-ref system
because C doesn't provide the automatization. What makes python's
parameter passing called as pass-by-object is because python provides
the automatization to make it seems that you can do true pass-by-
object.
Nov 5 '08 #112
On Nov 5, 2008, at 12:29 AM, Dennis Lee Bieber wrote:
>C++:
void foo(PersonPtr who) {
who->zipcode = 12345;
}
Please show us the type definition of "PersonPtr"
Sorry, that'd be obvious to anyone experienced in C++, but I shouldn't
assume. It would be:

typedef Person* PersonPtr;

It's a pretty standard idiom, precisely because it is so much more
common to need a variable of the pointer type than of the class type
itself.
>Java:
void foo(Person who) {
who.zipcode = 12345;
}
Please show us the type definition of "Person"
No. It's a class, and you can see that it defines a "zipcode" member;
nothing more is needed for the sake of this example. (The Java
designers realized that needing object reference variables is so
overwhelmingly more common than needing non-pointer variables, that
they eliminated the pointer syntax and made every variable of object
type actually a pointer to the object data, just as in RB, .NET, and
Python.)
>REALbasic/VB.Net:
Sub foo(ByVal who as Person)
who.zipcode = 12345
End Sub
Note they YOU, as the programmer, explicitly told the language to
use a call-by-value
Correct; these languages support both call-by-value and call-by-
reference. "ByVal" is the default, but you can still specify it (as
I've done here) if you want to be explicit.
-- and you still have not shown us the definition of "Person"
Right, again, there is nothing you need to know about it not already
evident from the example.
>Python:
def foo(who):
who.zipcode = 12345
Note that there is NO PROGRAMMER CONTROL over the passing mechanism.
Quite right. (Same too in Java.) Some languages offer both call-by-
value and call-by-reference; but Java and Python offer only call-by-
value.
>5. You see that the first three languages above are passing a
reference by value and using that to mutate and object, yet for
reasons still mysterious, the Python example (which has exactly the
same behavior) must be doing something different.
I do not... I see the programmer telling the language that a
reference is to be taken of some object and that this reference is
/then/ to be passed.
Quite right (and that's what I said). The reference is being passed.
By value. And then that reference is used to mutate an object.
AND the programmer is also (C++) explicitly dereferencing (by use of
->)!
Yep, "->" is the dereference operator in C++; in Java, RB, .NET, and
Python, it's ".". Different characters, same meaning.
The syntax, in C/C++ is different for
accessing the parameter by value vs by reference (pointer -- C++ is
smarter in that it allows declaring the parameter as a &ref and the
language automatically takes the address on the caller's side, and
dereferences on the called side -- but that notation is STILL a
programmer responsibility).
Careful here -- a &ref parameter really is passed by reference; that's
not the same as passing a pointer by value, which is what's shown
above. It's the C++ equivalent of the "ByRef" keyword in RB/VB.NET.
Java passes /objects/ by reference, but passes "native" types (base
numerics) by value
No, it passes everything by value. "who" in the Java example is not
an object; it is an object reference. It was passed by value. If it
were passed by reference, you'd be able to make a "swap" function that
exchanges the objects referred to by two variables, but you can't.
This is explained more fully here:

<http://javadude.com/articles/passbyvalue.htm>
-- can you create a Java example where you pass a base numeric by
reference?
No, because Java (like Python) has only call-by-value.
By your argument, even FORTRAN is call-by-value.
No, FORTRAN's an oddball: it passes everything by reference.
You obfuscate the mechanics used at the machine language level with
the semantics of the
language itself.
No, I haven't said anything at all about what's happening at the
machine language level, and I frankly don't care. This is about how
the language behaves.
FORTRAN is the language commonly used to explain call-by-reference!
Quite right. So, please try to convert any of those FORTRAN
explanations into Python or Java. Can't be done. In C++ or RB/
VB.NET, it can be done only by using the special by-reference syntax
(& or ByRef).

I'm not sure where you got the idea that I thought FORTRAN is call-by-
value. I never said or implied any such thing. And the examples
above aren't meant to prove that those languages are using by-value;
they're meant to show that mutating an object via a reference passed
in proves NOTHING about how that reference was passed. This is to
invalidate the argument (frequently heard around here) that Python
must use call-by-reference since you can mutate an object passed to a
function.

As should be painfully clear by now, that argument is total bunk. You
can pass an object reference by value, and use it to mutate the object
it refers to just fine. To test whether you're passing by reference
or by value, you need to instead assign a new value to the formal
parameter, and see whether that affects the actual parameter.
>
Cheers,
- Joe

Nov 6 '08 #113
On Nov 4, 2008, at 12:57 PM, Hendrik van Rooyen wrote:
>4. You now see how a mutating an object within a function tells you
NOTHING about how the reference to that object was passed.
>5. You see that the first three languages above are passing a
reference by value and using that to mutate and object, yet for
reasons still mysterious, the Python example (which has exactly the
same behavior) must be doing something different.

This is dialectic nit picking - WTF makes "passing a reference by
value"
different from "passing a reference" - the salient point is that its
a reference
that is passed
I know it seems nit-picky on the surface, but it is important. It is
the distinction that lets you answer whether:

def foo(x):
x = Foo()

x = Bar()
foo(x)

....results in x (after the call) now referring to a Foo, or still
referring to a Bar.

If x is a reference passed by value, then the assignment within the
foo method can't affect the x that was passed in. But if it is passed
by reference, then it does. (Also, if it is passed by reference, then
you probably wouldn't be able to pass in a literal or computed value,
but only a simple variable.)
- would you expect another level of indirection - a reference to
the reference, or what, before you admit that the thing that is
passed is a
reference and not a copied value of the OBJECT that is of interest.
Um, no, I've admitted that it's a reference all along. Indeed, that's
pretty much the whole point: that variables in Python don't contain
objects, but merely contain references to objects that are actually
stored somewhere else (i.e. on the heap). This is explicitly stated
in the Python docs [1], yet many here seem to want to deny it.
Looks to me that even if there were ten levels of indirection you
would still
insist that its a "pass by value" because in the end, its the actual
memory
address of the first pointer in the queue that is passed.
No, it's entirely possible for an OOP language to have pass by
reference, and, to put it your way, this adds one more level of
indirection. Look at the C++ and RB/VB.NET examples at [2]. But
Python and Java do not offer this option.
If that is what you mean, it is obviously trivially true - but then
ALL
calling can only be described as "call by value" - which makes
nonsense
of what the CS people have been doing all these years.
That would indeed be nonsense. But it's also not what I'm saying.
See [2] again for a detailed discussion and examples. Call-by-value
and call-by-reference are quite distinct.
"Calling by value" is not a useful definition of Pythons behaviour.
It really is, though. You have to know how the formal parameter
relates to the actual parameter. Is it a copy of it, or an alias of
it? Without knowing that, you don't know what assignments to the
formal parameter will do, or even what sort of arguments are valid.
Answer: it's a copy of it. Assignments don't affect the actual
parameter at all. This is exactly what "call by value" means.

Best,
- Joe

[1] http://www.python.org/doc/2.5.2/ext/refcounts.html
[2] http://www.strout.net/info/coding/valref/

Nov 6 '08 #114

I know this thread has grown quite personal for some of its
participants. I am posting in a spirit of peace and understanding :)

Joe Strout <jo*@strout.netwrites:
[...]
Um, no, I've admitted that it's a reference all along. Indeed, that's
pretty much the whole point: that variables in Python don't contain
objects, but merely contain references to objects that are actually
stored somewhere else (i.e. on the heap). This is explicitly stated
in the Python docs [1], yet many here seem to want to deny it.
You refer to docs about the *implementation* of Python in C. This is
irrelevant.

Also, you talk about variables 'containing' something. In Python,
variables don't contain anything, they're simply names for objects.
'Pass by value' is not relevant to Python as variables do not contain
anything. 'Pass by reference' is not relevant to Python as the language
doesn't have the concept of object reference (in the sense of e.g. C++
reference).

[...]
>"Calling by value" is not a useful definition of Pythons behaviour.

It really is, though. You have to know how the formal parameter
relates to the actual parameter. Is it a copy of it, or an alias of
it? Without knowing that, you don't know what assignments to the
formal parameter will do, or even what sort of arguments are valid.
Answer: it's a copy of it. Assignments don't affect the actual
parameter at all. This is exactly what "call by value" means.
Here lies, IMHO, the reason why you think you need Python to 'pass by
value'. As you believe that variables must contain something, you think
that assignment is about copying the content of a variable. Assignment
in Python is simply giving a new name to an object.

To understand variables (which I prefer to call 'names') and function
calls in Python you need simply to understand that:

- a variable is a name for an object
- assignment is naming an object
- the parameters of a function are local names for the call arguments
(I guess 'pass by object' is a good name).

Now quoting the start of your post:
On Nov 4, 2008, at 12:57 PM, Hendrik van Rooyen wrote:
>>5. You see that the first three languages above are passing a
reference by value and using that to mutate and object, yet for
reasons still mysterious, the Python example (which has exactly the
same behavior) must be doing something different.

This is dialectic nit picking - WTF makes "passing a reference by
value"
different from "passing a reference" - the salient point is that its
a reference
that is passed
I would say that an oject is passed, not a reference.
I know it seems nit-picky on the surface, but it is important. It is
the distinction that lets you answer whether:

def foo(x):
x = Foo()

x = Bar()
foo(x)

...results in x (after the call) now referring to a Foo, or still
referring to a Bar.
You don't need this to decide. This is what happens:

x = Bar() # Call this new Bar object 'x'
foo(x) # call function foo with argument the object known as 'x'

# Now, in foo:
def foo(x): # Call 'x' locally the object passed to foo
x = Foo() # Call 'x' locally this new Foo object.

Obviously after all this, 'x' is still the name of the Bar object
created at the start.
To sum up: for 'pass by value' to make sense in Python you need to
create an unnecessarily complex model of how Python works. By letting
go of 'pass by value' you can simplify your model of the language
(keeping it correct of course) and it fits in your brain more easily.

Of course your own model is valid but there is a better one which is
easier to grasp for people without a background in C/C++ - like
languages.

--
Arnaud
Nov 6 '08 #115
On Nov 6, 1:44*pm, Arnaud Delobelle <arno...@googlemail.comwrote:
I know this thread has grown quite personal for some of its
participants. *I am posting in a spirit of peace and understanding :)
Hear, hear.
You refer to docs about the *implementation* of Python in C. *This is
irrelevant.

Also, you talk about variables 'containing' something. *In Python,
variables don't contain anything, they're simply names for objects.
'Pass by value' is not relevant to Python as variables do not contain
anything. *'Pass by reference' is not relevant to Python as the language
doesn't have the concept of object reference (in the sense of e.g. C++
reference).
....
I would say that an oject is passed, not a reference.
....
To sum up: for 'pass by value' to make sense in Python you need to
create an unnecessarily complex model of how Python works. *By letting
go of 'pass by value' you can simplify your model of the language
(keeping it correct of course) and it fits in your brain more easily.

Of course your own model is valid but there is a better one which is
easier to grasp for people without a background in C/C++ - like
languages.
I agree, and I don't think we're giving Joe the proper credit for what
he knows and has worked on. Furthermore, his understanding of the
implementation of languages is thorough, and you can't have languages
without implementations. Though, you do not need to understand the
implementation to understand the language.

I haven't thought it through completely, but now that Joe mentions it,
it appears Python behaves the same as C++, if variables can't be
anything but pointers, parameters are all c-b-v, and you can't
dereference the l-h-s of an assignment ( '*a= SomeClass()' ).

When you're explaining Python to a beginner, you have to introduce a
new term either way. You'll either have to explain pointers, which
there are chapters and chapters on in introductory textbooks; or,
you'll have to explain a new calling mechanism, and give it a name.

I think pointer-by-value would be accurate, but by-value wouldn't be.
I would say that an oject is passed, not a reference.
I agree, and anything else would be overcomplicated.
Nov 6 '08 #116
On Nov 5, 2008, at 2:06 PM, Lie wrote:
><http://www.strout.net/info/coding/valref/>

I'm fed up with you.
I'm sorry -- I'm really not trying to be difficult. And it's odd that
you're fed up with me, yet you seem to be agreeing with me on at least
most points.
In Von Neumann Architecture computers, only pass-by-value is natively
supported. Other idioms are made on top of pass-by-value.
Well, sure. But a language may or may not naturally support the others.
That's why exclusively pass-by-value languages like C is most flexible
than other exclusively pass-by-<insertanythinghere>.

BUT the difference is clear, if you want to do pass-by-reference in C
(I prefer to call it faux pass-by-reference), you'd have to manually
find a variable's address, pass it by-value, then dereference the
address.
Agreed.
Compare with VB's ByRef or C++'s &, which does all that
_automatically_ for you behind the scene.
Agreed again.
Another example: pass-by-object.
Here's where we depart, I guess. I think there's no such thing (see <http://en.wikipedia.org/wiki/Evaluation_strategy
for example, and the dead-tree references I have on hand agree).
I disagree with the term pass-by-object-reference, since the notion
of object reference is unnecessary
in a true pass-by-object mechanism (i.e. we should travel outside VNA
realm for a true pass-by-object mechanism). Problem is: I'm not aware
of any computer architecture that can accommodate pass-by-object
natively or whether such architecture is feasible to be made.
I don't think it's necessary (or helpful) to reach down into the
architecture or implementation details. What matters is the behavior
as seen by the language user. Variables in a language could hold
actual object data (in which case "a = b" would copy the data from b
into a), or they could hold just references to object data that lives
elsewhere (in which case "a = b" would copy that reference, giving you
two references to the same object). In Python, they are of course
just references.

Then, and completely independent of that, variables could be passed
into a method by value or by reference (or by several other more
esoteric evaluation strategies that are rarely used, but "call by
object" isn't one of them). Again, it's easy to tell these apart with
a simple behavioral test. Python passes its object references by
value; changes to the formal parameter have no effect on the actual
parameter.
In pass-by-object, the whole object is passed around, not a copy of
the object like in pass-by-value or a copy of the pointer to the
object like in faux pass-by-reference.
I can't understand what that would mean, unless we imagine the
variable actually containing the object data; but it doesn't, or "a =
b" would copy that data, which clearly it does not.

Understanding that a name in Python is merely a reference to the
object, and not the object itself, seems to me to be one of the
fundamental truths that any beginning Python programmer must know.
This makes pass-by-object
actually closer to pass-by-reference than to pass-by-value, since the
notion of VNA's requirement for Object Reference means passing
pointers around. But don't let it confuse you, the pass-by-object
mechanism itself does not recognize Object Reference, unlike pass-by-
reference recognition of reference/pointer.
Sorry, it's confusing me whether I want it to or not.

And here's what I don't understand: object references are so simple,
why do people go to such great lengths to pretend that Python doesn't
have them, resulting in a far more complex and convoluted explanation
that is much harder to understand?
Now that I have clearly defined the line between pass-by-object and
pass-by-value, I'm left with you thinking what's the difference
between pass-by-object and pass-by-reference.
If they're that hard to tell apart, then Python doesn't have either,
since it is very clear and obvious that Python does not have pass-by-
reference (since you can't write a function to swap two parameters,
for example).
In pass-by-reference, names are _mnemonic to location in memory_.
In pass-by-object, names are _mnemonic to objects_.
These would be equivalent if objects live at some location in memory,
wouldn't they?
In pass-by-reference, when we assign a
value to the name, we'd assign a value _to the location in memory_. In
pass-by-object, when we assign a value to the name, we assign an
object _to the name_. When passing parameters, pass-by-reference
systems passed the memory address and alias that memory address to a
local name. In pass-by-object system, since the object itself has no
idea of its own name, so it is rebound to a local name. You can say
that pass-by-reference system is memory-location-centered, while pass-
by-object system is name-centered.
Hmm. I can only interpret "the object is rebound to a local name"
sounds the same to me as "a local variable is assigned a reference to
the object." Can you explain how they're different?

I see how what you're describing is different from pass by reference;
I just don't see how it's any different from pass by value.
To summarize, the key bit you're missing is built-in _automatic_
abstraction from pass-by-value. All pass-by-<insertanythingexcept
pass-by-value is an emulation over an architecture that can only
natively pass-by-value.
Yes, OK, that's great. But there are several standard pass-by-
somethings that are defined by the CS community, and which are simple
and clear and apply to a wide variety of languages. "Pass by object"
isn't one of them. I guess if you want to campaign for it as a
shorthand for "object reference passed by value," you could do that,
and it's not outrageous. But to anybody new to the term, you should
explain it as exactly that, rather than try to claim that Python is
somehow different from other OOP languages where everybody calls it
simply pass by value.
pass-by-reference is emulated in C, C++, and
VB by passing memory address/pointer but C isn't a by-ref system
because C doesn't provide the automatization.
Yes, that's true of C. I never argued that C had a by-ref mode. C++,
VB, and REALbasic all do, however. Python and Java do not.
What makes python's parameter passing called as pass-by-object is
because python provides
the automatization to make it seems that you can do true pass-by-
object.
OK, if there were such a thing as "pass-by-object" in the standard
lexicon of evaluation strategies, I would be perfectly happy saying
that a system has it if it behaves as though it has it, regardless of
the underpinnings.

My objection to this term is simply that it is made up and
nonstandard, and adds no new value to the discussion. To me, "object
references passed by value" is simple and clear, where as "pass by
object" means nothing (until you explain that it means the former).

However, if you really think the term is that handy, and we want to
agree to say "Python uses pass by object" and answer the inevitable
"huh?" question with "that's shorthand for object references passed by
value," then I'd be OK with that.

Best,
- Joe

Nov 6 '08 #117
On Nov 6, 2008, at 12:44 PM, Arnaud Delobelle wrote:
I know this thread has grown quite personal for some of its
participants. I am posting in a spirit of peace and understanding :)
Thanks, I'll do the same.
>Um, no, I've admitted that it's a reference all along. Indeed,
that's
pretty much the whole point: that variables in Python don't contain
objects, but merely contain references to objects that are actually
stored somewhere else (i.e. on the heap). This is explicitly stated
in the Python docs [1], yet many here seem to want to deny it.

You refer to docs about the *implementation* of Python in C. This is
irrelevant.
It's supportive. I don't understand how/why anybody would deny that
Python names are references -- it's all over the place, from any
discussion of "reference counting" (necessary to understand the life
cycle of Python object) to understanding the basics of what "a = b"
does. It seems absurd to argue that Python does NOT use references.
So the official documentation calmly discussing Python references,
with no caveats about it being internal implementation detail, seemed
relevant.
Also, you talk about variables 'containing' something. In Python,
variables don't contain anything, they're simply names for objects.
You say "names for", I say "references to". We're saying the same
thing (though I'm saying it with terminology that is more standard, at
least in the wider OOP world).
'Pass by value' is not relevant to Python as variables do not contain
anything. 'Pass by reference' is not relevant to Python as the
language
doesn't have the concept of object reference (in the sense of e.g. C++
reference).
Both are relevant to answering simple questions, like what happens to
x in this case:

def foo(spam):
spam = 5
foo(x)

This is a basic and fundamental thing that a programmer of a language
should know. If it's call-by-reference, then x becomes 5. If it's
call-by-value, it does not.

Why the resistance to these simple and basic terms that apply to any
OOP language?
Here lies, IMHO, the reason why you think you need Python to 'pass by
value'. As you believe that variables must contain something, you
think
that assignment is about copying the content of a variable.
Assignment
in Python is simply giving a new name to an object.
What does "give a new name to an object" mean? I submit that it means
exactly the same thing as "assigns the name to refer to the object".
There certainly is no difference in behavior that anyone has been able
to point out between what assignment does in Python, and what
assignment does in RB, VB.NET, Java, or C++ (in the context of object
pointers, of course). If the behavior is the same, why should we make
up our own unique and different terminology for it?
To understand variables (which I prefer to call 'names') and function
calls in Python you need simply to understand that:

- a variable is a name for an object
A reference to an object, got it.
- assignment is naming an object
Assigning the reference to the object, yes.
- the parameters of a function are local names for the call arguments
Agreed; they're not aliases of the call arguments.
(I guess 'pass by object' is a good name).
Well, I'm not sure why that would be. What you've just described is
called "pass by value" in every other language.
I would say that an oject is passed, not a reference.
That seems to contradict the actual behavior, as well as what you said
yourself above. The only way I know how to interpret "an object is
passed" is "the data of that object is copied onto the stack". But of
course that's not what happens. What actually happens is what you
said above: a name (reference) is assigned to the object. The name is
a reference; it is made to refer to the same thing that the argument
(actual parameter) referred to. This is exactly what "the reference
is passed" means, nothing more or less.
>I know it seems nit-picky on the surface, but it is important. It is
the distinction that lets you answer whether:

def foo(x):
x = Foo()

x = Bar()
foo(x)

...results in x (after the call) now referring to a Foo, or still
referring to a Bar.

You don't need this to decide. This is what happens:

x = Bar() # Call this new Bar object 'x'
In other words, make 'x' refer to this new object.
foo(x) # call function foo with argument the object known as 'x'
Yes. But what does that mean? Does the parameter within 'foo' become
an alias of x, or a copy of it? That's what we DO need to decide.
# Now, in foo:
def foo(x): # Call 'x' locally the object passed to foo
I think you mean here that local 'x' is made to refer to the object
passed to foo. Agreed. It is NOT an alias of the actual parameter.
And that's what we need to know. So it's not call-by-reference, it's
call-by-value; the value of x (a reference to whatever object Bar()
returned) is copied from the value of the parameter (a reference to
that same object, of course).
x = Foo() # Call 'x' locally this new Foo object.
Make 'x' refer to the new Foo() result, yes.
Obviously after all this, 'x' is still the name of the Bar object
created at the start.
Obvious only once you've determined that Python is call-by-value. If
it were like FORTRAN, where everything is call-by-reference, then that
wouldn't be the case at all; the assignment within the function would
affect the variable (or name, if you prefer) passed in.
To sum up: for 'pass by value' to make sense in Python you need to
create an unnecessarily complex model of how Python works.
I have to disagree. The model is simple, self-consistent, and
consistent with all other languages. It's making up terms and trying
to justify them and get out of the logical knots (such as your claim
above that the object itself is passed to a method) that is
unnecessarily complex.
By letting go of 'pass by value' you can simplify your model of the
language
(keeping it correct of course) and it fits in your brain more easily.
I'm afraid I don't see that.
Of course your own model is valid but there is a better one which is
easier to grasp for people without a background in C/C++ - like
languages.
Well, if by C/C++-like languages, you mean also Java, VB.NET, and so
on, then maybe you're right -- perhaps my view is colored by my
experience with those. But alternatively, perhaps there are enough
Python users without experience in other OOP languages, that the
standard terminology was unfamiliar to them, and they made up their
own, resulting in the current linguistic mess.

Best,
- Joe

Nov 7 '08 #118
Aaron Brady wrote:
and you can't have languages without implementations.
This is either a claim that languages are their own implementations, or
an admission that human brains are the implementation of all languages
thought of by human brains, coupled with a claim that there cannot be
languages not thought of by humans, or just wrong in terms of the common
meaning of algorithmic implementation of an interpreter. There are many
algorithm languages without such implementations. They were once called
'pseudocode'. (I don't know if that term is still used much.) Hence my
oxymoronic definition, a decade ago, of Python as 'executable pseudocode'.
Though, you do not need to understand the
implementation to understand the language.
Languages are typically defined before there is any implementation.
They are implemented if they are understood as being worth the effort.
I haven't thought it through completely, but now that Joe mentions it,
it appears Python behaves the same as C++,
Python and C/C++ have completely different object and data models. You
and Joe are completely welcome to understand/model Python in terms of
the C implementation, if you wish, but it not necessary and, I believe,
a disservice to push such a model on beginners as *the* way to model Python.
if variables can't be
anything but pointers, parameters are all c-b-v, and you can't
dereference the l-h-s of an assignment ( '*a= SomeClass()' ).
I don't understand this.
When you're explaining Python to a beginner, you have to introduce a
new term either way. You'll either have to explain pointers, which
Python has no concept of pointers.
there are chapters and chapters on in introductory textbooks; or,
you'll have to explain a new calling mechanism, and give it a name.
I disagree. In everyday life, we have multiple names for objects and
classes of objects. We nearly always define procedures in terms of
generic object classes (common nouns) rather than particular objects.
We apply procedures by binding generic names to particular objects, by
associating them with objects, by filling in the named blanks. This is
what Python does. Except for the particular formalized syntax, there is
nothing new, not even the idea of a specialized procedure language.

def make_cookies(flour, oil, sugar, egg, bowl, spoon, cookie_pan, oven):
"flour, oil, and sugar are containers with respectively at least 2
cups, 1 tablespoon, and 1/4 cup of the indicated material"
mix(bowl, spoon, measure(flour, '2 cups'), measure(sugar, '1/4 cup'))
<etc>

OK, there is one important difference. The concrete referents for the
parameters are non-physical information objects rather than physical
objects.
>I would say that an oject is passed, not a reference.
I agree, and anything else would be overcomplicated.
To me, 'pass' implies movement, but in Python, objects don't really have
a position and hence cannot move. So I would say that an object is
associated (with a parameter). 'Associating' is a primitive operation
for Python interpreters. If and when all parameters get associated with
something, the function code is activated. Then the return object gets
associated with the call expression in the computation graph.

Terry Jan Reedy

Nov 7 '08 #119
On Nov 6, 6:00*pm, Terry Reedy <tjre...@udel.eduwrote:
Aaron Brady wrote:
and you can't have languages without implementations.

This is either a claim that languages are their own implementations, or
an admission that human brains are the implementation of all languages
thought of by human brains, coupled with a claim that there cannot be
languages not thought of by humans, or just wrong in terms of the common
meaning of algorithmic implementation of an interpreter. *There are many
algorithm languages without such implementations. *They were once called
'pseudocode'. (I don't know if that term is still used much.) *Hence my
oxymoronic definition, a decade ago, of Python as 'executable pseudocode'..
I was just saying that Joe has a good idea for one way to implement
Python.
Python and C/C++ have completely different object and data models. *You
and Joe are completely welcome to understand/model Python in terms of
the C implementation, if you wish, but it not necessary and, I believe,
a disservice to push such a model on beginners as *the* way to model Python.
You're asking about people's thought processes when they write a
program. In chess, I sometimes think, "If I move here, he moves
there," etc., but not always; sometimes I just visualize pieces in
places. In Python, if I want a function that, say, duplicates the
first and last elements of a sequence type, I visualize one parameter,
and some code that operates on it.

def duper( a ):
a.insert( 0, a[ 0 ] )
a.append( a[ -1 ] )

Someone else with no experience, or certain incompatible experience,
might visualize this:

def duper( a ):
a= a[ 0 ] + a + a[ -1 ]

As you can see, they know a lot of Python already. What are they
missing?
if variables can't be
anything but pointers, parameters are all c-b-v, and you can't
dereference the l-h-s of an assignment ( '*a= SomeClass()' ).

I don't understand this.
If you restricted a C program as follows:
- variables can only be pointers
- no pointers to pointers
- no dereferencing l-h-s of assignment statements

It would look at the very least a lot like Python, or as Joe holds,
exactly like Python.

snip.
I disagree. *In everyday life, we have multiple names for objects and
classes of objects. We nearly always define procedures in terms of
generic object classes (common nouns) rather than particular objects.
We apply procedures by binding generic names to particular objects, by
associating them with objects, by filling in the named blanks. *This is
what Python does. *Except for the particular formalized syntax, there is
nothing new, not even the idea of a specialized procedure language.
To examine the natural language (NL) equivalents of these issues a
little.

Here's a question I posed to Joe:

a) 'Fido' is a reference to a dog
b) Fido is a reference to a dog
c) 'Fido' is the name of a dog
d) Fido is the name of a dog
e) 'Fido' is a dog
f) Fido is a dog

Which are true?

I have no problems with (c) and (f), and many natural languages
(possibly being strictly spoken) do not distinguish (c) from (d).
Similarly,

Old McDonald had a dog and Bingo was it's name.
(*) Old McDonald had a dog and Bingo was it. (* marks non-standard)
(*) Old McDonald had a dog and it was Bingo.

I want to give a code name to Fido: Rex. What language do I use to
inform my audience ("spies"), and what statements are subsequently
true? Then, I want to write instructions to friends on how to walk
dogs in my neighborhood, still in natural language.

_How to walk a dog_
Take the dog out the door
Turn right at the end of the drive
etc.

Nothing mysterious. Same thing with instructions for vaccinating
them. However, if I want to model dogs, simulate them, etc., I'll
keep some running state information about them: think its chart at the
vet.

Dog:
Fido:
Last walked: 10 a.m.
Needs to be walked: False

At 4 p.m., I'm going through the charts, and I notice Fido hasn't been
walked, so I change the 'Needs to be walked' entry to true.

Then some members of "spies" walks into the vet, and ask if Rex needs
to be walked.

What things in this story are names, variables, dogs, references,
objects, pointers, types, classes, procedures, functions, arguments,
parameters, formal parameters, by-value parameters, by-reference
parameters, by-share parameters, etc.? How many names does Fido have,
what are they, what is Fido, what is Rex, etc.? Keep in mind there
are seldom quotes in spoken language; people have to make gestures or
be explicit in such cases as they need to indicate their presence.

"Quote Fido quote is the name of a dog, but Fido is not." (Actual
transcription.)

Keep answers to less than 500 words. Also, reevaluate the uses of
'the' and 'a' in the multiple choice question: Is 'Fido' the name of a
dog, a name of a dog, or a name of the dog?
def make_cookies(flour, oil, sugar, egg, bowl, spoon, cookie_pan, oven):
* * *"flour, oil, and sugar are containers with respectively at least 2
cups, 1 tablespoon, and 1/4 cup of the indicated material"
* * *mix(bowl, spoon, measure(flour, '2 cups'), measure(sugar, '1/4cup'))
yield cookies #yum
OK, there is one important difference. *The concrete referents for the
parameters are non-physical information objects rather than physical
objects.
This is actually underestimated. Equality and identity as defined on
mathematical ("ideal") / logical objects isn't the same as our "real"
notions of them. Words are sort of in between, giving rise to e.g.
the difference between numbers and numerals.
I would say that an oject is passed, not a reference.
I agree, and anything else would be overcomplicated.

To me, 'pass' implies movement, but in Python, objects don't really have
a position and hence cannot move. *So I would say that an object is
associated (with a parameter).
Further complicating matters, is the function, its parameters,
variables, code, etc. remain in existence between calls to it. Argh!
'Associating' is a primitive operation for Python interpreters.
Interesting. If I may be so bold as to ask, is it for C code, C
compilers, and/or C programs?

snip.

All due respect.
Nov 7 '08 #120
On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote:
that's
pretty much the whole point: that variables in Python don't contain
objects, but merely contain references to objects that are actually
stored somewhere else (i.e. on the heap).
You're wrong, Python variables don't contain *anything*. Python variables
are names in a namespace. But putting that aside, consider the Python
code "x = 1". Which statement would you agree with?

(A) The value of x is 1.

(B) The value of x is an implementation-specific thing which is
determined at runtime. At the level of the Python virtual machine, the
value of x is arbitrary and can't be determined.

If you answer (A), then your claim that Python is call-by-value is false.
If you answer (B), then your claim that Python is call-by-value is true
but pointless, obtuse and obfuscatory.
This is explicitly stated in
the Python docs [1], yet many here seem to want to deny it.
[1] http://www.python.org/doc/2.5.2/ext/refcounts.html

You have a mysterious and strange meaning of the word "explicitly". Would
you care to quote what you imagine is this explicit claim?
>Looks to me that even if there were ten levels of indirection you would
still
insist that its a "pass by value" because in the end, its the actual
memory
address of the first pointer in the queue that is passed.

No, it's entirely possible for an OOP language to have pass by
reference, and, to put it your way, this adds one more level of
indirection. Look at the C++ and RB/VB.NET examples at [2]. But Python
and Java do not offer this option.
Yes, you are right, Python does not offer pass by reference. The
canonical test for "call by reference" behaviour is to write a function
that does this:

x = 1
y = 2
swap(x, y)
assert x == 2 and y == 1

If you can write such a function, your language may be call-by-reference.
If you can't, it definitely isn't c-b-r. You can't write such a function
in standard Python, so Python isn't c-b-r.
The canonical test for "call by value" semantics is if you can write a
function like this:

x = [1] # an object that supports mutation
mutate(x)
assert x == [1]

If mutations to an argument in a function are *not* reflected in the
caller's scope, then your language may be call-by-value. But if mutations
are visible to the caller, then your language is definitely not c-b-v.

Python is neither call-by-reference nor call-by-value.

>If that is what you mean, it is obviously trivially true - but then ALL
calling can only be described as "call by value" - which makes nonsense
of what the CS people have been doing all these years.

That would indeed be nonsense. But it's also not what I'm saying. See
[2] again for a detailed discussion and examples. Call-by-value and
call-by-reference are quite distinct.
And also a false dichotomy.

>"Calling by value" is not a useful definition of Pythons behaviour.

It really is, though. You have to know how the formal parameter relates
to the actual parameter. Is it a copy of it, or an alias of it?
And by definition, "call by value" means that the parameter is a copy. So
if you pass a ten megabyte data structure to a function using call-by-
value semantics, the entire ten megabyte structure is copied.

Since this does not happen in Python, Python is not a call-by-value
language. End of story.
Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.
Lies, all lies. Python doesn't copy variables unless you explicitly ask
for a copy. That some implementations of Python choose to copy pointers
rather than move around arbitrarily large blocks of memory instead is an
implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.
Assignments don't affect the actual parameter at
all. This is exactly what "call by value" means.
Nonsense. I don't know where you get your definitions from, but it isn't
a definition anyone coming from a background in C, Pascal or Fortran
would agree with.


--
Steven
Nov 7 '08 #121
First, I want to thank everyone for your patience -- I think we're
making progress towards a consensus.

On Nov 6, 2008, at 8:48 PM, Steven D'Aprano wrote:
>that's
pretty much the whole point: that variables in Python don't contain
objects, but merely contain references to objects that are actually
stored somewhere else (i.e. on the heap).

You're wrong, Python variables don't contain *anything*. Python
variables
are names in a namespace.
I think we're saying the same thing. What's a name? It's a string of
characters used to refer to something. That which refers to something
is a reference. The thing it refers to is a referent. I was trying
to avoid saying "the value of an object reference is a reference to an
object" since that seems tautological and you don't like my use of the
word "value," but I see you don't like "contains" either.

Maybe we can try something even wordier: a variable in Python is, by
some means we're not specifying, associated with an object. (This is
what I mean when I say it "refers" to the object.) Can we agree that
far?

Now, when you pass a variable into a method, the formal parameter gets
associated with same object the actual parameter was associated with.
I like to say that the object reference gets copied into the formal
parameter, since that's a nice, simple, clear, and standard way of
describing it. I think you object to this way of saying it. But are
we at least in agreement that this is what happens?
But putting that aside, consider the Python
code "x = 1". Which statement would you agree with?

(A) The value of x is 1.
Only speaking loosely (which we can get away with because numbers are
immutable types, as pointed out in the last section of [1]).
(B) The value of x is an implementation-specific thing which is
determined at runtime. At the level of the Python virtual machine, the
value of x is arbitrary and can't be determined.
Hmm, this might be true to somebody working at the implementation
level, but I think we're all agreed that that's not the level of this
discussion. What's relevant here is how the language actually
behaves, as observable by tests written in that language.
If you answer (A), then your claim that Python is call-by-value is
false.
Correct.
If you answer (B), then your claim that Python is call-by-value is
true
but pointless, obtuse and obfuscatory.
Correct again. My answer is:

(C) The value of x is a reference to an immutable object with the
value of 1. (That's too wordy for casual conversation so we might
casually reduce this to (A), as long as we all understand that (A) is
not actually true. It's a harmless fiction as long as the object is
immutable; it becomes important when we're dealing with mutable
objects.)
>This is explicitly stated in
the Python docs [1], yet many here seem to want to deny it.
>[1] http://www.python.org/doc/2.5.2/ext/refcounts.html

You have a mysterious and strange meaning of the word "explicitly".
Would
you care to quote what you imagine is this explicit claim?
A few samples: "The chosen method is called reference counting. The
principle is simple: every object contains a counter, which is
incremented when a reference to the object is stored somewhere, and
which is decremented when a reference to it is deleted. When the
counter reaches zero, the last reference to the object has been
deleted and the object is freed. ...Python uses the traditional
reference counting implementation..."

This seems like a point we really shouldn't need to argue. Do you
really want to defend the claim that Python does not use references?
Yes, you are right, Python does not offer pass by reference. The
canonical test for "call by reference" behaviour is to write a
function
that does this:

x = 1
y = 2
swap(x, y)
assert x == 2 and y == 1

If you can write such a function, your language may be call-by-
reference.
If you can't, it definitely isn't c-b-r. You can't write such a
function
in standard Python, so Python isn't c-b-r.
Whew! That's a relief. A week ago (or more?), it certainly sounded
like some here were claiming that Python is c-b-r (usually followed by
some extended hemming and hawing and except-for-ing to explain why you
couldn't do the above).
The canonical test for "call by value" semantics is if you can write a
function like this:

x = [1] # an object that supports mutation
mutate(x)
assert x == [1]

If mutations to an argument in a function are *not* reflected in the
caller's scope, then your language may be call-by-value. But if
mutations
are visible to the caller, then your language is definitely not c-b-v.
Aha. So, in your view, neither C, nor C++, nor Java, nor VB.NET are c-
b-v, since all of those support passing an object reference into a
function, and using that reference to mutate the object.

Your view is at odds with the standard definition, though; in fact I'm
pretty sure we could dig up C and Java specs that explicitly spell out
their c-b-v semantics, and RB and VB.NET pretty clearly mean "ByVal"
to indicate by-value in those languages.

The canonical test of c-b-v is whether a *reassignment* of the formal
parameter is visible to the caller. Simply using the parameter for
something (such as dereferencing it to find and change data that lives
on the heap) doesn't prove anything at all about how the parameter was
passed.
Python is neither call-by-reference nor call-by-value.
That can be true only if at least one of the following is true:

1. Python's semantics are different from C/C++ (restricted to
pointers), Java, and RB/VB.NET; or
2. C/C++ (restricted to pointers), Java, and RB/VB.NET are not call-by-
value.

I asked you before which of these you believed to be the case, so we
could focus on that, but I must have missed your reply. Can you
please clarify?

From your above c-b-v test, I guess you would argue point 2, that
none of those languages are c-b-v. If so, then we can proceed to
examine that in more detail. Is that right?
>That would indeed be nonsense. But it's also not what I'm saying.
See
[2] again for a detailed discussion and examples. Call-by-value and
call-by-reference are quite distinct.

And also a false dichotomy.
I've never claimed these are the only options; just that they're the
only ones actually used in any of the languages under discussion. If
you think Python uses call by name, call by need, call by macro
expansion, or something else at [2], please do say which one. "Call
by object", as far as I can tell, is just a made-up term for call-by-
value when the value is an object reference. (And I'm reasonably OK
with that as long as we're all agreed that that is what it means.)
>>"Calling by value" is not a useful definition of Pythons behaviour.

It really is, though. You have to know how the formal parameter
relates
to the actual parameter. Is it a copy of it, or an alias of it?

And by definition, "call by value" means that the parameter is a
copy. So
if you pass a ten megabyte data structure to a function using call-by-
value semantics, the entire ten megabyte structure is copied.
Right. And if (as is more sensible) you pass a reference to a ten MB
data structure to a function using call-by-value, then the reference
is copied.
Since this does not happen in Python, Python is not a call-by-value
language. End of story.
So your claim is that any language that includes references (which is
all OOP languages, as far as I'm aware), is not call-by-value?
>Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.

Lies, all lies. Python doesn't copy variables unless you explicitly
ask
for a copy.
Hmm, I'm struggling to understand why you would say this. Perhaps you
mean that Python doesn't copy *objects* unless you explicitly ask for
a copy. That's certainly true. But it does copy references in many
circumstances, including in assignment statements, and parameter
passing.
That some implementations of Python choose to copy pointers
rather than move around arbitrarily large blocks of memory instead
is an
implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.
I agree that under the hood, there are probably other ways to get the
same behavior. What's important is to know whether the formal
parameter is an alias of the actual parameter, or its own independent
local variable that (let me try to say it more like your way here)
happens to be initially associated with the same referent as the
actual parameter. This obviously has behavioral consequences, as you
showed above.

A concise way to describe the behavior of Python and other languages
is to simply say: the object reference is copied into the formal
parameter.
>Assignments don't affect the actual parameter at
all. This is exactly what "call by value" means.

Nonsense. I don't know where you get your definitions from, but it
isn't
a definition anyone coming from a background in C, Pascal or Fortran
would agree with.
Well I can trivially refute that by counterexample: I come from a
background in C, Pascal, and FORTRAN, and I agree with it.

As for where I get my definitions from, I draw from several sources:

1. Dead-tree textbooks
2. Wikipedia [2] (and yes, I know that has to be taken with a grain of
salt, but it's so darned convenient)
3. My wife, who is a computer science professor and does compiler
research
4. http://javadude.com/articles/passbyvalue.htm (a brief but excellent
article)
5. Observations of the "ByVal" (default) mode in RB and VB.NET
6. My own experience implementing the RB compiler (not that
implementation details matter, but it forced me to think very
carefully about references and parameter passing for a very long time)

Not that I'm trying to argue from authority; I'm trying to argue from
logic. I suspect, though, that your last comment gets to the crux of
the matter, and reinforces my guess above: you don't think c-b-v means
what most people think it means. Indeed, you don't think any of the
languages shown at [1] are, in fact, c-b-v languages. If so, then we
should focus on that and see if we can find a definitive answer.

Best,
- Joe

[1] http://www.strout.net/info/coding/valref/
[2] http://en.wikipedia.org/wiki/Evaluation_strategy

Nov 7 '08 #122
Aaron Brady wrote:
On Nov 6, 6:00 pm, Terry Reedy <tjre...@udel.eduwrote:
>'Associating' is a primitive operation for Python interpreters.

Interesting. If I may be so bold as to ask, is it for C code, C
compilers, and/or C programs?
Sorry, I should have specified for the abstract definition of a Python
interpreter, and perhaps for people. Computer programs need an
implementation in terms of computer memory, etc.

Nov 7 '08 #123
Steven D'Aprano wrote:
On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote:
[...]
And by definition, "call by value" means that the parameter is a copy. So
if you pass a ten megabyte data structure to a function using call-by-
value semantics, the entire ten megabyte structure is copied.

Since this does not happen in Python, Python is not a call-by-value
language. End of story.
>Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.

Lies, all lies. Python doesn't copy variables unless you explicitly ask
for a copy. That some implementations of Python choose to copy pointers
rather than move around arbitrarily large blocks of memory instead is an
implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.
[...]

Are you sure you meant to write this?

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #124
Steven D'Aprano wrote:
On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote:
[...]
And by definition, "call by value" means that the parameter is a copy. So
if you pass a ten megabyte data structure to a function using call-by-
value semantics, the entire ten megabyte structure is copied.

Since this does not happen in Python, Python is not a call-by-value
language. End of story.
>Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.

Lies, all lies. Python doesn't copy variables unless you explicitly ask
for a copy. That some implementations of Python choose to copy pointers
rather than move around arbitrarily large blocks of memory instead is an
implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.
[...]

Are you sure you meant to write this?

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #125
Joe Strout wrote:
First, I want to thank everyone for your patience -- I think we're
making progress towards a consensus.
Phew.
>
>But putting that aside, consider the Python
code "x = 1". Which statement would you agree with?

(A) The value of x is 1.

Only speaking loosely (which we can get away with because numbers are
immutable types, as pointed out in the last section of [1]).
I'd agree this is a valid way to describe the post-condition of the
assignment.
>(B) The value of x is an implementation-specific thing which is
determined at runtime. At the level of the Python virtual machine, the
value of x is arbitrary and can't be determined.

Hmm, this might be true to somebody working at the implementation level,
but I think we're all agreed that that's not the level of this
discussion. What's relevant here is how the language actually behaves,
as observable by tests written in that language.
I'd actually say "x contains a reference to 1", claim that was
equivalent to (A) above and cite Humpty Dumpty as my justification [1].
>If you answer (A), then your claim that Python is call-by-value is false.

Correct.
>If you answer (B), then your claim that Python is call-by-value is true
but pointless, obtuse and obfuscatory.

Correct again. My answer is:

(C) The value of x is a reference to an immutable object with the value
of 1. (That's too wordy for casual conversation so we might casually
reduce this to (A), as long as we all understand that (A) is not
actually true. It's a harmless fiction as long as the object is
immutable; it becomes important when we're dealing with mutable objects.)
I am unsure here as to why you find it necessary to refer to 1's
immutability. How does this alter the essence of the situation?

[...]
>
Not that I'm trying to argue from authority; I'm trying to argue from
logic. I suspect, though, that your last comment gets to the crux of
the matter, and reinforces my guess above: you don't think c-b-v means
what most people think it means. Indeed, you don't think any of the
languages shown at [1] are, in fact, c-b-v languages. If so, then we
should focus on that and see if we can find a definitive answer.
You're right. Observable progress, I think.

regards
Steve

[1] http://www.sundials.org/about/humpty.htm
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #126
Steve Holden <st***@holdenweb.comwrites:
One of the reasons for Python's continue march towards world
domination (allow me my fantasies) is its consistent simplicity.
Those last two words would be my candidate for the definition of
"Pythonicity".
+1 QOTW

--
\ Eccles: “I'll get [the job] too, you'll see. I'm wearing a |
`\ Cambridge tie.†Greenslade: “What were you doing there?†|
_o__) Eccles: “Buying a tie.†—The Goon Show, _The Greenslade Story_ |
Ben Finney
Nov 7 '08 #127
On Fri, 07 Nov 2008 00:44:21 -0500, Steve Holden wrote:
Steven D'Aprano wrote:
>On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote:
[...]
>And by definition, "call by value" means that the parameter is a copy.
So if you pass a ten megabyte data structure to a function using
call-by- value semantics, the entire ten megabyte structure is copied.

Since this does not happen in Python, Python is not a call-by-value
language. End of story.
>>Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.

Lies, all lies. Python doesn't copy variables unless you explicitly ask
for a copy. That some implementations of Python choose to copy pointers
rather than move around arbitrarily large blocks of memory instead is
an implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.
[...]

Are you sure you meant to write this?
I'm not sure I understand what you're getting at. The only thing I can
imagine is that you think there's some sort of contradiction between my
two statements. I don't see why you think so. In principle one could
create an implementation of Python with no stack at all, where everything
lives in the heap, and all argument passing is via moving the actual
objects ("large blocks of memory") rather than references to the objects.

I don't mean to imply that this is a practical way to go about
implementing Python, particularly given current computer hardware where
registers are expensive and the call stack is ubiquitous. But there are
other computing models, such as the "register machine" model which uses a
hypothetically-infinite number of registers, no stack and no heap. With
sufficient effort, one could implement a Python compiler using only a
Turing Machine. Turing Machines don't have call-by-anything semantics.
What would that say about Python?

Alternatively, you're commenting about my comment about copying pointers.
I thought I had sufficiently distinguished between what takes place at
the level of the Python VM (nothing is copied without an explicit request
to copy it) and what takes place in the VM's implementation (the
implementation is free to copy whatever pointers it wants as an
optimization). If I failed to make that clear, I hope I have done so now.

Pointers do not exist at the level of the Python VM, but they clearly
exist in the C implementation. We agree that C is call-by-value. CPython
is (obviously) built on top of C's call-by-value semantics, by passing
pointers (or references if you prefer) to objects. But that doesn't imply
that Python's calling semantics are the same as C's.

Algol is call-by-name. Does anyone doubt that we could develop an Algol
implementation of Python that used nothing but call-by-name semantics at
the implementation level? Would that mean that Python was call-by-name?

The point is that Joe's argument is based on a confusion between the C
implementation (calling a function with argument x makes a copy of a
pointer to x and puts it into the stack for the function) and what
happens at the level of the Python language.

--
Steven
Nov 7 '08 #128
Steven D'Aprano wrote:
On Fri, 07 Nov 2008 00:44:21 -0500, Steve Holden wrote:
>Steven D'Aprano wrote:
>>On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote:
[...]
>>And by definition, "call by value" means that the parameter is a copy.
So if you pass a ten megabyte data structure to a function using
call-by- value semantics, the entire ten megabyte structure is copied.

Since this does not happen in Python, Python is not a call-by-value
language. End of story.

Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.
Lies, all lies. Python doesn't copy variables unless you explicitly ask
for a copy. That some implementations of Python choose to copy pointers
rather than move around arbitrarily large blocks of memory instead is
an implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.
[...]

Are you sure you meant to write this?

I'm not sure I understand what you're getting at. The only thing I can
imagine is that you think there's some sort of contradiction between my
two statements. I don't see why you think so. In principle one could
create an implementation of Python with no stack at all, where everything
lives in the heap, and all argument passing is via moving the actual
objects ("large blocks of memory") rather than references to the objects.

I don't mean to imply that this is a practical way to go about
implementing Python, particularly given current computer hardware where
registers are expensive and the call stack is ubiquitous. But there are
other computing models, such as the "register machine" model which uses a
hypothetically-infinite number of registers, no stack and no heap. With
sufficient effort, one could implement a Python compiler using only a
Turing Machine. Turing Machines don't have call-by-anything semantics.
What would that say about Python?

Alternatively, you're commenting about my comment about copying pointers.
I thought I had sufficiently distinguished between what takes place at
the level of the Python VM (nothing is copied without an explicit request
to copy it) and what takes place in the VM's implementation (the
implementation is free to copy whatever pointers it wants as an
optimization). If I failed to make that clear, I hope I have done so now.

Pointers do not exist at the level of the Python VM, but they clearly
exist in the C implementation. We agree that C is call-by-value. CPython
is (obviously) built on top of C's call-by-value semantics, by passing
pointers (or references if you prefer) to objects. But that doesn't imply
that Python's calling semantics are the same as C's.

Algol is call-by-name. Does anyone doubt that we could develop an Algol
implementation of Python that used nothing but call-by-name semantics at
the implementation level? Would that mean that Python was call-by-name?

The point is that Joe's argument is based on a confusion between the C
implementation (calling a function with argument x makes a copy of a
pointer to x and puts it into the stack for the function) and what
happens at the level of the Python language.
I am probably egregiously misunderstanding. The practical difficulty
with the "moving huge blocks of data" approach would appear to emerge
when a function that gets passed an instance of some container then
calls another function that references the same container as a global,
for example.

Again, I don't think we disagree about how Python actually works, but it
seemed to me that your statement obscured rather than helped.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #129
Steven D'Aprano wrote:
On Fri, 07 Nov 2008 00:44:21 -0500, Steve Holden wrote:
>Steven D'Aprano wrote:
>>On Thu, 06 Nov 2008 09:59:37 -0700, Joe Strout wrote:
[...]
>>And by definition, "call by value" means that the parameter is a copy.
So if you pass a ten megabyte data structure to a function using
call-by- value semantics, the entire ten megabyte structure is copied.

Since this does not happen in Python, Python is not a call-by-value
language. End of story.

Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.
Lies, all lies. Python doesn't copy variables unless you explicitly ask
for a copy. That some implementations of Python choose to copy pointers
rather than move around arbitrarily large blocks of memory instead is
an implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.
[...]

Are you sure you meant to write this?

I'm not sure I understand what you're getting at. The only thing I can
imagine is that you think there's some sort of contradiction between my
two statements. I don't see why you think so. In principle one could
create an implementation of Python with no stack at all, where everything
lives in the heap, and all argument passing is via moving the actual
objects ("large blocks of memory") rather than references to the objects.

I don't mean to imply that this is a practical way to go about
implementing Python, particularly given current computer hardware where
registers are expensive and the call stack is ubiquitous. But there are
other computing models, such as the "register machine" model which uses a
hypothetically-infinite number of registers, no stack and no heap. With
sufficient effort, one could implement a Python compiler using only a
Turing Machine. Turing Machines don't have call-by-anything semantics.
What would that say about Python?

Alternatively, you're commenting about my comment about copying pointers.
I thought I had sufficiently distinguished between what takes place at
the level of the Python VM (nothing is copied without an explicit request
to copy it) and what takes place in the VM's implementation (the
implementation is free to copy whatever pointers it wants as an
optimization). If I failed to make that clear, I hope I have done so now.

Pointers do not exist at the level of the Python VM, but they clearly
exist in the C implementation. We agree that C is call-by-value. CPython
is (obviously) built on top of C's call-by-value semantics, by passing
pointers (or references if you prefer) to objects. But that doesn't imply
that Python's calling semantics are the same as C's.

Algol is call-by-name. Does anyone doubt that we could develop an Algol
implementation of Python that used nothing but call-by-name semantics at
the implementation level? Would that mean that Python was call-by-name?

The point is that Joe's argument is based on a confusion between the C
implementation (calling a function with argument x makes a copy of a
pointer to x and puts it into the stack for the function) and what
happens at the level of the Python language.
I am probably egregiously misunderstanding. The practical difficulty
with the "moving huge blocks of data" approach would appear to emerge
when a function that gets passed an instance of some container then
calls another function that references the same container as a global,
for example.

Again, I don't think we disagree about how Python actually works, but it
seemed to me that your statement obscured rather than helped.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #130
On Thu, 06 Nov 2008 21:31:16 -0700, Joe Strout wrote:
>You're wrong, Python variables don't contain *anything*. Python
variables are names in a namespace.

I think we're saying the same thing. What's a name? It's a string of
characters used to refer to something. That which refers to something
is a reference.
In some sense, I have to agree with that. "Reference" as a plain English
word is very abstract.

The thing it refers to is a referent. I was trying to
avoid saying "the value of an object reference is a reference to an
object" since that seems tautological and you don't like my use of the
word "value," but I see you don't like "contains" either.
I'm happier with the idea that a name in Python "refers to" an object
than your claim that "variables" contain a reference to an object. Let me
explain:

In languages such as C and Pascal, a variable is a named memory location
with an implied size. For the sake of the argument, let's assume
variables are all two bytes in size, i.e. they can hold a single short
integer. So, if the name 'x' refers to location 0x23A782, and the two
bytes at that location are 0x0001, then we can legitimately say that the
location 0x23A782 (otherwise known as 'x') _contains_ 1 because the byte
pattern representing 1 is at that memory location.

But in Python, what you've been calling "variables" is explicitly a
*mapping* between a name and a value. Unlike variables above, the
compiler can't map a name to a memory location. At run time, the VM has
to search a namespace for the name. If you disassemble Python byte-code,
you will see things like:

LOAD_NAME 1 (x)

If you want to talk about something containing the value, that something
would be the namespace, not the name: the name is the key in the hash
table, and is a separate piece of data to the value. The key and the
value are at different locations, you can't meaningfully say that the
value is contained by the key, for the same reason that given a list

[10, 11, 12, 13, 14, 15]

you wouldn't say that the int 12 was contained by the number 2.

Maybe we can try something even wordier: a variable in Python is, by
some means we're not specifying, associated with an object. (This is
what I mean when I say it "refers" to the object.) Can we agree that
far?
So far.

Now, when you pass a variable into a method, the formal parameter gets
associated with same object the actual parameter was associated with.
Agreed.

I like to say that the object reference gets copied into the formal
parameter, since that's a nice, simple, clear, and standard way of
describing it. I think you object to this way of saying it. But are we
at least in agreement that this is what happens?
At the implementation level of CPython, yes. In abstract, no. In
abstract, we can't make *any* claims about what happens beyond the Python
code, because we don't know how the VM is implemented. Perhaps it is a
giant pattern in Conway's cellular automata "Life", which is Turing
Complete.

In practice, any reasonable implementation of Python on existing computer
hardware is going to more-or-less do what the CPython implementation
does. But just because every existing implementation does something
doesn't mean it's not an implementation detail.

>But putting that aside, consider the Python code "x = 1". Which
statement would you agree with?

(A) The value of x is 1.

Only speaking loosely (which we can get away with because numbers are
immutable types, as pointed out in the last section of [1]).
Why "speaking loosely"?

At the level of Python code, the object you have access to is nothing
more or less than 1. There is a concrete representation of the abstract
Platonic number ONE, and that concrete representation is written as 1.

The fact that the object 1 is immutable rather than mutable is
irrelevant. After x = [] the value of x is the empty list.

As far as I am concerned, this is one place where the plain English
definition of the word "value" is the only meaningful definition: "what
is denoted by a symbol". Or if you prefer, "what the symbol represents".
At the language level, x=1 means that x represents the object 1, nothing
more and nothing less, regardless of how the mechanics of that
representation are implemented.

The value of a variable is whatever thing you assign to that variable. If
that thing is the int 1, then the value is the int 1. If the thing is a
list, the value is that list. If the thing is a pointer, the value is a
pointer. (Python doesn't give you access to pointers, but other languages
do.) Whatever mechanism is used to implement that occurs at a deeper
level. In Pascal and C, bytes are copied into memory locations (which is
actually implemented by flipping bits at one location to match the state
of bits at another location). In CPython and Java, pointers or references
are created and pointed at complex data structures called objects. That's
an implementation detail, just like flipping bits is an implementation
detail.

If you don't agree with me on this, I'm afraid that your understanding of
value is so different from mine that I fear we will never find any common
ground. I'm afraid that in this context I consider any other definition
of "value" to be obtuse and obfuscatory and out-and-out harmful.
>(B) The value of x is an implementation-specific thing which is
determined at runtime. At the level of the Python virtual machine, the
value of x is arbitrary and can't be determined.

Hmm, this might be true to somebody working at the implementation level,
Okay, we agree on that.

but I think we're all agreed that that's not the level of this
discussion. What's relevant here is how the language actually behaves,
as observable by tests written in that language.
As far as I can see, that implementation level _is_ the level you are
talking at. You keep arguing that the value of x is a reference to the
object, a reference which is implementation specific and determined at
runtime.
>If you answer (A), then your claim that Python is call-by-value is
false.

Correct.
>If you answer (B), then your claim that Python is call-by-value is true
but pointless, obtuse and obfuscatory.

Correct again.
Well. I'm not sure what else I can say to that other than, "Why on earth
would you prefer a pointless, obtuse and obfuscatory claim over one which
is equally true but far more useful and simple?"
My answer is:

(C) The value of x is a reference to an immutable object with the value
of 1. (That's too wordy for casual conversation so we might casually
reduce this to (A), as long as we all understand that (A) is not
actually true. It's a harmless fiction as long as the object is
immutable; it becomes important when we're dealing with mutable
objects.)
But it doesn't matter. And that's important. I've seen this before, in
other people. They get hung up about the difference between mutable and
immutable objects and start assuming a difference in Python's behaviour
that simply isn't there. When assigning to a name, Python makes no
distinction between mutable and immutable objects:

>>dis.dis( compile('x=set([1]); y=frozenset([1])', '', 'exec') )
1 0 LOAD_NAME 0 (set)
3 LOAD_CONST 0 (1)
6 BUILD_LIST 1
9 CALL_FUNCTION 1
12 STORE_NAME 1 (x)
15 LOAD_NAME 2 (frozenset)
18 LOAD_CONST 0 (1)
21 BUILD_LIST 1
24 CALL_FUNCTION 1
27 STORE_NAME 3 (y)
30 LOAD_CONST 1 (None)
33 RETURN_VALUE
>>This is explicitly stated in
the Python docs [1], yet many here seem to want to deny it.
>>[1] http://www.python.org/doc/2.5.2/ext/refcounts.html

You have a mysterious and strange meaning of the word "explicitly".
Would you care to quote what you imagine is this explicit claim?

A few samples: "The chosen method is called reference counting. The
principle is simple: every object contains a counter, which is
incremented when a reference to the object is stored somewhere, and
which is decremented when a reference to it is deleted. When the counter
reaches zero, the last reference to the object has been deleted and the
object is freed. ...Python uses the traditional reference counting
implementation..."
Implementation details again. It says nothing about what is visible at
the level of Python code.

This seems like a point we really shouldn't need to argue. Do you
really want to defend the claim that Python does not use references?
Python does not use references. Python uses names and objects. The
CPython implementation implements such names and objects using references
(pointers). Other implementations are free to make other choices at the
implementation level.

At the Python level, the programmer has access to objects:

(1, 3, [], None)

is a tuple (an object) consisting of four objects 1, 3, an empty list and
None. There's no capacity to request a reference to an object: if there
was, it would be like Pascal's var parameters.

At the implementation level, the above tuple is implemented (in part) by
four pointers. But that's invisible at the Python level. It doesn't exist
at the Python level: you can't access those pointers, you can't do
anything with them, except indirectly by manipulating names and objects.

Here's an analogy: at the Python level we say that strings are immutable:
they can't be changed. But at the implementation level that's clearly
nonsense: strings are merely bytes no different from any other bytes, and
they are as mutable as any others. But from Python code, the programmer
has no way to mutate a string. Such behaviour isn't part of Python. We
can rightly say that Python has no mutable strings, even though at the
implementation level strings are mutable.
>Yes, you are right, Python does not offer pass by reference. The
canonical test for "call by reference" behaviour is to write a function
that does this:

x = 1
y = 2
swap(x, y)
assert x == 2 and y == 1

If you can write such a function, your language may be call-by-
reference.
If you can't, it definitely isn't c-b-r. You can't write such a
function
in standard Python, so Python isn't c-b-r.

Whew! That's a relief. A week ago (or more?), it certainly sounded
like some here were claiming that Python is c-b-r (usually followed by
some extended hemming and hawing and except-for-ing to explain why you
couldn't do the above).
Yes. Such confusion is very common, because people discover that Python
isn't call-by-value since mutations to arguments in a function are
visible outside of the function, and assume that therefore Python must be
call-by-reference.

>The canonical test for "call by value" semantics is if you can write a
function like this:

x = [1] # an object that supports mutation
mutate(x)
assert x == [1]

If mutations to an argument in a function are *not* reflected in the
caller's scope, then your language may be call-by-value. But if
mutations
are visible to the caller, then your language is definitely not c-b-v.

Aha. So, in your view, neither C, nor C++, nor Java, nor VB.NET are c-
b-v, since all of those support passing an object reference into a
function, and using that reference to mutate the object.
Take C out of that list. C is explicitly call-by-value, since it always
does copying of values. If you want to avoid copying the value, you have
to write your function to accept a pointer to the value you care about
and then dereference the pointer inside the function.

As for C++, Java and VB.NET, I would argue that using the term call-by-
value for them is misleading. I'm not the only such person who believes
so:

"As in Java, the calling semantics are call-by-sharing: the formal
argument variable and the actual argument share the same value, at least
until the argument variable is assigned to. Assignments to the argument
variable do not affect the value passed; however, if the value passed was
an array, assignments to elements of that array will be visible from the
calling context as well, since it shares the same array object."

http://www.cs.cornell.edu/courses/cs...iota/iota.html

Trust me, I didn't write that.
Your view is at odds with the standard definition, though; in fact I'm
pretty sure we could dig up C and Java specs that explicitly spell out
their c-b-v semantics, and RB and VB.NET pretty clearly mean "ByVal" to
indicate by-value in those languages.
I accept that C (like Pascal) is c-b-v. Given the following C code:

int count;
int x[1000];
for( count = 0; count < 1000; count++ )
x[count] = count;
the value of the variable 'x' is an array of ints 0,1,2,...999. When you
call a function with argument x, the entire array is copied. Call-by-
value: the variable's value is copied into the function's scope.

For Java to be considered c-b-v, we have to agree that the value of x
following that assignment is not the array of ints that the source code
suggests it is, but some arbitrary pointer to that array. If we agree on
that definition, we can agree that Java is c-b-v, but I maintain it is a
foolish definition.

I can't imagine what reason people had for tossing out the commonsense
meaning of the word "value". What benefit does it give? For those whose
first language was Pascal or Fortran or C and had only heard of two
calling conventions it avoids the need to learn the name for a third
convention, but the cost is that c-b-v no longer has a single meaning. It
now has at least two meanings: C call-by-value is different from Java
call-by-value, because when you call a C function with an array the
entire array is copied, and when you call a Java function with an array
the entire array is *not* copied. Different program behaviour with the
same name.

That's bad enough when it happens with an element of language syntax but
it is unforgivable when it happens to something which is supposed to be
generic to all languages.

Not only do you lose the regular dictionary meaning of the word value,
but you introduce a second meaning to call-by-value. When you say
"Language Foo is call-by-value", you have no way of telling what
listeners will understand by that. If they come from a Pascal or C
background, they will understand one thing ("values are copied"), and if
they come from a Java or VB.NET background they will understand something
very different ("sometimes values are copied, and sometimes pointers to
the value are copied").

The canonical test of c-b-v is whether a *reassignment* of the formal
parameter is visible to the caller.
That's just the same test for c-b-r: it's a variation of swap(x, y) but
using only one variable. That's equivalent to assuming that c-b-r and c-b-
v are a dichotomy: if a language isn't one, it must be the other. Wrong,
false, harmful!

Simply using the parameter for
something (such as dereferencing it to find and change data that lives
on the heap) doesn't prove anything at all about how the parameter was
passed.
But it does: if a mutation to the argument is visible to the caller, then
you know you haven't mutated a copy. If no copy was made, then it isn't
call-by-value.

>Python is neither call-by-reference nor call-by-value.

That can be true only if at least one of the following is true:

1. Python's semantics are different from C/C++ (restricted to pointers),
Java, and RB/VB.NET; or
Why would you restrict C/C++ to pointers? Are you now going to argue that
these languages have different calling conventions depending on the type
of the argument?

In C, the calling convention is precisely the same whether the argument
is a pointer or an int. In both cases, the value is copied.

Python's semantics are different from C since values are not copied when
you pass them to a function, but (as fair as I know) the same as that of
the others.

2. C/C++ (restricted to pointers), Java, and RB/VB.NET are not call-by-
value.
Take C out of that list and I will agree.

I asked you before which of these you believed to be the case, so we
could focus on that, but I must have missed your reply. Can you please
clarify?

From your above c-b-v test, I guess you would argue point 2, that
none of those languages are c-b-v. If so, then we can proceed to
examine that in more detail. Is that right?
Sure.

>>That would indeed be nonsense. But it's also not what I'm saying. See
[2] again for a detailed discussion and examples. Call-by-value and
call-by-reference are quite distinct.

And also a false dichotomy.

I've never claimed these are the only options; just that they're the
only ones actually used in any of the languages under discussion. If
you think Python uses call by name, call by need, call by macro
expansion,
No, none of those.

or something else at [2], please do say which one. "Call by
object", as far as I can tell, is just a made-up term for call-by- value
when the value is an object reference.
And you think that "call-by-reference" or "call-by-value" is anything
other than "made-up"? What, you think that these terms have always
existed, as far back as language? They're made-up terms too. I would say
that the value is the object, full stop. The reference is an
implementation detail.

As we've repeatedly said, "call-by-sharing" has a good pedigree: it goes
back at least to Barbara Liskov and CLU in 1974, in the dawn of object-
oriented programming.

http://en.wikipedia.org/wiki/Barbara_Liskov

The real question isn't why Python should use the term "call-by-sharing",
but why the Java and VB people didn't use it.
(And I'm reasonably OK with that
as long as we're all agreed that that is what it means.)
>>>"Calling by value" is not a useful definition of Pythons behaviour.

It really is, though. You have to know how the formal parameter
relates
to the actual parameter. Is it a copy of it, or an alias of it?
False dichotomy again. The correct answer is, "Neither. It _is_ the
actual parameter." We can prove this by using Python's scoping rules:
>>def func(y):
.... print x is y
....
>>x = ["something arbitrary"]
func(x)
True

In case you think this is an artifact of mutable objects:
>>x = "something immutable"
func(x)
True
The value of x and the value of y are the same object. But the names are
different. (They would be different even if the function parameter was
called 'x', because it is in a different namespace.) Nothing we do to the
name y can affect the name x. But things that we do to the object bound
to y *can* affect the object bound to x, because they are the same object.
>And by definition, "call by value" means that the parameter is a copy.
So
if you pass a ten megabyte data structure to a function using call-by-
value semantics, the entire ten megabyte structure is copied.

Right. And if (as is more sensible) you pass a reference to a ten MB
data structure to a function using call-by-value, then the reference is
copied.
Sure. I agree. But in this case, the reference is the value. In Pascal,
you would do something like this:

x := enormous_array(); {returns a 10MB array}
y := func(^x);

if you couldn't or didn't write func to use a var parameter.
>Since this does not happen in Python, Python is not a call-by-value
language. End of story.

So your claim is that any language that includes references (which is
all OOP languages, as far as I'm aware), is not call-by-value?
No, I'm not making that claim. Calling conventions and the existence of
references in the implementation of an OO language are orthogonal: one
does not imply anything about the other.

Consider a hypothetical OO language where variables are memory locations.
x=Foo would set the value of the variable x to some object Foo. As an
implementation detail, this might be implemented just as you say: the
variable (memory location) x contains a reference to the object Foo, just
like Java, except without primitive types.

Now we call a function func(x). What happens next?

Well, knowing that the language is OO doesn't tell us *anything* about
what happens next. We can probably make an educated guess that, if the
language is running on a von Neumann machine (a safe bet in the real
world!), there's probably a stack involved, and the implementation will
probably work by pushing references on the stack. What else can we
predict? Nothing. Here are a couple of alternative calling behaviours:

- The implementation makes a copy of the object Foo, creates a new
reference to it, and assigns that reference to the formal parameter of
the function. I would call that "call-by-value". What would you call it?

- The implementation makes a copy of the reference to object Foo, and
assigns it to the formal parameter of the function. Following Barbara
Liskov, I would call that "call-by-sharing". Following the effbot, I
would also accept "call-by-object".

- The implementation makes a reference to the location of x, rather than
a reference to the object, and passes that to the function. Reassignments
to the formal parameter are reflected in the caller's scope. That would
be call-by-reference.

Any of these would be reasonable choices for a designer to make, although
the first one has all the disadvantages of call-by-value in languages
like C and Pascal. Nevertheless, if you want that behaviour in your OOP
language, you can have it.
>>Without knowing that, you don't know what assignments to the formal
parameter will do, or even what sort of arguments are valid. Answer:
it's a copy of it.

Lies, all lies. Python doesn't copy variables unless you explicitly ask
for a copy.

Hmm, I'm struggling to understand why you would say this. Perhaps you
mean that Python doesn't copy *objects* unless you explicitly ask for a
copy. That's certainly true.
We can agree on this.

But it does copy references in many circumstances, including in
assignment statements, and parameter passing.
At the implementation level, not at the Python level.

>That some implementations of Python choose to copy pointers rather than
move around arbitrarily large blocks of memory instead is an
implementation detail. It's an optimization and irrelevant to the
semantics of argument passing in Python.

I agree that under the hood, there are probably other ways to get the
same behavior. What's important is to know whether the formal parameter
is an alias of the actual parameter, or its own independent local
variable that (let me try to say it more like your way here) happens to
be initially associated with the same referent as the actual parameter.
This obviously has behavioral consequences, as you showed above.

A concise way to describe the behavior of Python and other languages is
to simply say: the object reference is copied into the formal parameter.
Hence the alias for "call-by-sharing", "call-by-object-reference".
Personally I find that term too long and unwieldy and prefer call-by
either sharing or object.
>>Assignments don't affect the actual parameter at all. This is exactly
what "call by value" means.

Nonsense. I don't know where you get your definitions from, but it
isn't
a definition anyone coming from a background in C, Pascal or Fortran
would agree with.

Well I can trivially refute that by counterexample: I come from a
background in C, Pascal, and FORTRAN, and I agree with it.
Well there you go. Serves me right for making a sweeping generalization.

As for where I get my definitions from, I draw from several sources:

1. Dead-tree textbooks
2. Wikipedia [2] (and yes, I know that has to be taken with a grain of
salt, but it's so darned convenient)
3. My wife, who is a computer science professor and does compiler
research
4. http://javadude.com/articles/passbyvalue.htm (a brief but excellent
article)
5. Observations of the "ByVal" (default) mode in RB and VB.NET 6. My own
experience implementing the RB compiler (not that implementation details
matter, but it forced me to think very carefully about references and
parameter passing for a very long time)
Which makes you so close to the trees that you can't see the forest.
You're not think at the level of Python code. You're not even thinking at
the level of the Python virtual machine. You're thinking about what
happens to make the Python virtual machine work.
Not that I'm trying to argue from authority; I'm trying to argue from
logic. I suspect, though, that your last comment gets to the crux of
the matter, and reinforces my guess above: you don't think c-b-v means
what most people think it means.
No, I make no claim about who is in a majority. What I argue is that the
Java and VB communities have taken a term with an established meaning,
and are using it for something which is at best pedantically true at a
deeper implementation level. I think they are foolish to have done so,
and their actions have led to imprecision in language: "call-by-value" is
no longer a single strategy with a single observable behaviour, but now
refers to at least two incompatible behaviours: Pascal/C style, and Java/
VB style. I don't accept that alternative meaning, because I insist that
at the level of Python code, after x=1 the value of x is 1 and not an
arbitrary, artificial, implementation-dependent reference to 1.

--
Steven
Nov 7 '08 #131
On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote:
I am probably egregiously misunderstanding. The practical difficulty
with the "moving huge blocks of data" approach would appear to emerge
when a function that gets passed an instance of some container then
calls another function that references the same container as a global,
for example.
I have no doubt whatsoever that such an implementation would be fragile,
complicated, convoluted and slow. In other words, it would be terrible.
But that's merely a Quality of Implementation issue. It would still be
Python.
--
Steven
Nov 7 '08 #132
Steven D'Aprano wrote:
On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote:
>I am probably egregiously misunderstanding. The practical difficulty
with the "moving huge blocks of data" approach would appear to emerge
when a function that gets passed an instance of some container then
calls another function that references the same container as a global,
for example.

I have no doubt whatsoever that such an implementation would be fragile,
complicated, convoluted and slow. In other words, it would be terrible.
But that's merely a Quality of Implementation issue. It would still be
Python.

OK, more specifically: I don't see how changes to the copy of the
(structure referenced by) the argument would be reflected in the global
structure. In other words, it seems to involve a change of semantics to
me, so I think I am misunderstanding you.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #133
On Fri, 07 Nov 2008 11:37:28 -0500, Steve Holden wrote:
Steven D'Aprano wrote:
>On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote:
>>I am probably egregiously misunderstanding. The practical difficulty
with the "moving huge blocks of data" approach would appear to emerge
when a function that gets passed an instance of some container then
calls another function that references the same container as a global,
for example.

I have no doubt whatsoever that such an implementation would be
fragile, complicated, convoluted and slow. In other words, it would be
terrible. But that's merely a Quality of Implementation issue. It would
still be Python.

OK, more specifically: I don't see how changes to the copy of the
(structure referenced by) the argument would be reflected in the global
structure. In other words, it seems to involve a change of semantics to
me, so I think I am misunderstanding you.
What, you want me to come up with an implementation? Okay, fine.

The VM keeps a list of the namespaces that contain such "cloned" objects.
After each Python statement is executed, before the next one gets to run,
the VM runs through that list and synchronizes each object in the
caller's scope with the value of its clone in the function scope.

--
Steven
Nov 7 '08 #134
On Fri, 07 Nov 2008 11:37:28 -0500, Steve Holden wrote:
Steven D'Aprano wrote:
>On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote:
>>I am probably egregiously misunderstanding. The practical difficulty
with the "moving huge blocks of data" approach would appear to emerge
when a function that gets passed an instance of some container then
calls another function that references the same container as a global,
for example.

I have no doubt whatsoever that such an implementation would be
fragile, complicated, convoluted and slow. In other words, it would be
terrible. But that's merely a Quality of Implementation issue. It would
still be Python.

OK, more specifically: I don't see how changes to the copy of the
(structure referenced by) the argument would be reflected in the global
structure. In other words, it seems to involve a change of semantics to
me, so I think I am misunderstanding you.
Of course every copy has a list of references to other copies and time
stamps associated with every attribute. So when you access an attribute
the implementation first chases all the links to the copies, and checks
if the attribute has a newer time stamp there, so the value has to be
copied back. =:o)

More serious: If you start to design distributed object oriented systems
with call-by-sharing semantics you may end up with actually copying the
value and propagating changes or checking for them in other copies.

Ciao,
Marc 'BlackJack' Rintsch
Nov 7 '08 #135
Joe Strout wrote:
On Nov 6, 2008, at 10:35 PM, Steve Holden wrote:
Note: I tried to say "name" above instead of "variable" but I couldn't
bring myself to do it -- "name" seems to generic to do that job.
Python has two types of names. Some complex objects -- modules,
classes, and functions, and wrappers and subclasses thereof, have
'definition names' that are used instead of a 'value' to print a
representation. Otherwise, names are identifiers, the term used in the
grammar.

But I agree even two meaning is one too many. Maybe 'label' would be a
better short form for 'identifier'. 'Labeling' might be clearer for
many beginners than 'name-binding'.
Lots
of things have names that are not variables: modules have names, classes
have names, methods have names, and so do variables. If I say "name,"
an astute listener would reasonably say "name of what"
Common nouns, when instantiated, become the name of whatever particular
object they are associated with.
-- and I don't
want to have to say "name of some thing in a name space which can be
flexibly associated with an object" when the simple term "variable"
seems to work as well.
'Variable' has many more meanings than 'name' or 'label' and overall
seems to be more confusing, not less. I say this as an empirical
observation of c.l.p postings. You yourself switched back and forth
between two different meanings.
I'm with you there. To me, the consistent simplicity is exactly this:
all variables are object references, and these are always passed by value.
The me, this implies that the corresponding parameter should become a
reference to that reference value. In any case, the last 10 years of
this newsgroups shows that describing Python calling as 'by value'
confuses people so that they are surprised that mutating a list inside a
function results in the list being mutated outside the function.
But Python doesn't have those simple types, so there is a temptation to
try to skip this generalization and say that references are not values,
The Python Language Reference uses the word 'reference' but does not
define it. I take it to be 'whatever information an interpreter uses to
associate a name or collection slot with an object and to retrieve the
object (and possibly its value) when requested'.
Well of course. I'm pretty sure I've said repeatedly that Python
variables refer to objects on the heap.
Built-in objects are not allocated on the heap.
>(Please replace "heap" with "object space" if you prefer.)
They are in abstract object space, although CPython occasionally leaks
the abstraction in error messages about not being able to modify
non-heap objects.
I'm only saying that Python variables
don't contain any other type of value than references.
One problem with the word 'variable' is that variables are somethings
thought of as 'containing', as you did above. So you switch back and
forth between 'variables *are* references' and 'variables *contain*
references'. Whereas a name (noun) definitely *is* a reference and not
a container.
Ditto right back at you. :) So maybe here's the trouble: since all
Python variables are references,
Back to *is*.
But continuing to attempt to gloss over that fact, when you come to
parameter passing,
I believe most of us here try to follow Knuth's lead and use 'parameter'
for the local names and 'argument' for the value/object that gets
associated with the name.
not copied). You also have to describe the assignment operator as
In Python, assignment is not an operator by intentional design.
different from all other languages, since clearly that's not copying the
object either.
Python's assignment *statement* does what we routinely do in everyday
life when we assign new labels to things, whether permanently or
temporarily.
An assignment copies the RHS
reference into the LHS variable, nothing more or less.
Back to variable as container.
An assignment associates the RHS object(s) with the LHS target(s).
A parameter copies the argument reference into the formal parameter,
A function call associates objects derived from the argument expressions
and stored defaults with the function parameters.
Isn't that simple, clear, and far easier to explain?
Applied to my version, I agree ;-).

I wonder if that could be tested systematically. Perhaps we could round
up 20 newbies, divide them into two groups of 10, give each one a 1-page
explanation either based on passing object references by-value, or
passing values sort-of-kind-of-by-reference, and then check their
comprehension by predicting the output of some code snippets. That'd be
very interesting.
Except for your garbling of the alternative to your version, I agree.
I suspect that different people might do better with different
explanations, depending on background.
In my case, my understanding of Python became clear only once I stopped
listening to all the confusing descriptions here, and realized that
Python is no different from other OOP languages I already knew.
Whereas I learned Python without any OOP experience but enough knowledge
of C++ to know I did not want to go there.

Terry Jan Reedy

Nov 7 '08 #136
Steven D'Aprano wrote:
On Fri, 07 Nov 2008 11:37:28 -0500, Steve Holden wrote:
>Steven D'Aprano wrote:
>>On Fri, 07 Nov 2008 10:50:55 -0500, Steve Holden wrote:

I am probably egregiously misunderstanding. The practical difficulty
with the "moving huge blocks of data" approach would appear to emerge
when a function that gets passed an instance of some container then
calls another function that references the same container as a global,
for example.
I have no doubt whatsoever that such an implementation would be
fragile, complicated, convoluted and slow. In other words, it would be
terrible. But that's merely a Quality of Implementation issue. It would
still be Python.

OK, more specifically: I don't see how changes to the copy of the
(structure referenced by) the argument would be reflected in the global
structure. In other words, it seems to involve a change of semantics to
me, so I think I am misunderstanding you.

What, you want me to come up with an implementation? Okay, fine.

The VM keeps a list of the namespaces that contain such "cloned" objects.
After each Python statement is executed, before the next one gets to run,
the VM runs through that list and synchronizes each object in the
caller's scope with the value of its clone in the function scope.
Right, so we replace references to values with references to namespaces?

Anyway, thanks. I'm really glad you stated up-front that this was not a
practical execution scheme.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #137
Steven D'Aprano wrote:
On Fri, 07 Nov 2008 08:48:19 -0700, Joe Strout wrote:
Unfortunately, the term "name" is *slightly* ambiguous in Python. There
are names, and then there are objects which have a name attribute, which
holds a string. This attribute is usually called __name__ but sometimes
it's called other things, like func_name.
3.0 corrects that divergence.
>>def foo(): pass
>>foo.__name__
'foo'
You're assuming that call-by-sharing isn't a standard term. That's not
true. It's a standard term that is sadly not well known, I believe
because of the ignorance of most coders to the history of their own
discipline. (I include myself in that.)
-------------------------
http://en.wikipedia.org/wiki/Call_by...all_by_sharing

Call by sharing

Also known as "call by object" or "call by object-sharing" is an
evaluation strategy first named by Barbara Liskov et al for the language
CLU in 1974[1]. It is used by languages such as Python[2] and Iota and
(as argued by some[3]) Java, although the term is not in common use by
the Java community. Call-by-sharing implies that values in the language
are based on objects rather than primitive types.

The semantics of call-by-sharing differ from call-by-reference in that
assignments to function arguments within the function aren't visible to
the caller (unlike by-reference sematics). However since the function
has access to the same object as the caller (no copy is made), mutations
to those objects within the function are visible to the caller, which
differs from call-by-value semantics.

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.

---------------------------------
http://www.pmg.csail.mit.edu/papers/...ef/node34.html

Call by Sharing
The caller and called routine communicate only through the argument and
result objects; routines do not have access to any variables of the caller.

After the assignments of actual arguments to formal arguments, the
caller and the called routine share objects. If the called routine
modifies a shared object, the modification is visible to the caller on
return. The names used to denote the shared objects are distinct in the
caller and called routine; if a routine assigns an object to a formal
argument variable, there is no effect on the caller. From the point of
view of the invoked routine, the only difference between its formal
argument variables and its other local variables is that the formals are
initialized by its caller.

==========================
Python object *do* have access to surrounding scopes, but the second
paragraph exact described Python, as does the corresponding Wikipedia entry.
==================================
myweb.lmu.edu/dondi/fall2004/cmsi585/subroutines-in-depth.pdf

• Call by sharing
– Used by languages where variables are already references to objects
– Parameters are references to objects, but assignments to those parameters
don’t change them at the level of the caller — e.g. Java uses call-by-value
for primitives (int, char) and uses call-by-sharing for Objects
-------------------------------------------

And Google had other links to course notes using 'call by sharing'

Terry Jan Reedy

Nov 7 '08 #138
On Nov 7, 2008, at 12:13 PM, Terry Reedy wrote:
Python has two types of names. Some complex objects -- modules,
classes, and functions, and wrappers and subclasses thereof, have
'definition names' that are used instead of a 'value' to print a
representation. Otherwise, names are identifiers, the term used in
the grammar.

But I agree even two meaning is one too many. Maybe 'label' would
be a better short form for 'identifier'. 'Labeling' might be
clearer for many beginners than 'name-binding'.
I actually rather like "identifier," though it seems a little too
technical for casual use. On the other hand, "label" seems too
arbitrary -- "variable" is a common term, and accurate enough to me.
'Variable' has many more meanings than 'name' or 'label' and overall
seems to be more confusing, not less. I say this as an empirical
observation of c.l.p postings. You yourself switched back and forth
between two different meanings.
Did I? What were they? I thought I had a clear idea what I mean by
it (and, as far as I know, it's consistent with what everybody else
means by it too). The only oddity in Python is that things you might
not expect to be variables (such as module names) actually are. But
that's a succinct way to express that observation; saying "module
names are variables too" seems to imply all the right things (e.g.
that you can assign new values to them, or assign them to other
variables).
>I'm with you there. To me, the consistent simplicity is exactly
this: all variables are object references, and these are always
passed by value.

To me, this implies that the corresponding parameter should become a
reference to that reference value.
Really? You've just described passing an object reference by
reference. If "passing a reference by value" implies adding an
additional reference to it, then what would "passing a reference by
reference" mean to you? And, examining your thought process, can you
explain where that implication came from?
In any case, the last 10 years of this newsgroups shows that
describing Python calling as 'by value' confuses people so that they
are surprised that mutating a list inside a function results in the
list being mutated outside the function.
Yes, but that would happen ONLY when they also think that a variable
actually contains the object data. And since there are many here
trying to claim exactly that, I think that is the root cause of the
problem, not calling parameter passing "by value."

And this belief (that the value of a variable is an object) leads to
other mistaken beliefs too, such as that assignment should make a copy:

x = y
x.foo = bar

Anyone surprised by the list mutation inside a function should also be
surprised to find that y.foo = bar. I think we should simply address
the root cause of that confusion, not try to redefine their
understanding of how parameters are passed, and ALSO redefine what
assignment means.
>But Python doesn't have those simple types, so there is a
temptation to try to skip this generalization and say that
references are not values,

The Python Language Reference uses the word 'reference' but does not
define it. I take it to be 'whatever information an interpreter
uses to associate a name or collection slot with an object and to
retrieve the object (and possibly its value) when requested'.
Sure, that's fine. It doesn't really matter how it's implemented.
What matters is that a name or collection slot somehow refers to an
object, and whatever the form of that reference is, it is copied (*)
to the LHS of an assignment or to the formal parameter of a function
call.

(*) I was going to say "transferred" but when something is transferred
from A to B, it implies that B gains it and A loses it. "Copied" has
the right implication: that afterwards, both A and B now have it.
I'm only saying that Python variables
don't contain any other type of value than references.

One problem with the word 'variable' is that variables are
somethings thought of as 'containing', as you did above. So you
switch back and forth between 'variables *are* references' and
'variables *contain* references'.
Perhaps this is the two meanings you mentioned above. I'm not sure I
see any useful dichotomy here, though. In C, we say that this
variable is an integer, that variable is a character, the one over
there is a double. This is unambiguous shorthand for "the declared
type of this variable is such-and-so", and each such variable contains
data of that type. So there's no harm in saying that a variable is an
integer, or that a variable contains an integer, as the context
requires.

In Python, AFAICT, there is only one type, the object reference. So,
the type of every variable is 'reference', and each one contains a
reference.
Whereas a name (noun) definitely *is* a reference and not a
container.
Yes, I'll grant you that about it. "Label" and "identifier" has that
connotation as well. But as long as we recognize that what a Python
variable contains is a reference, I don't see that it matters. And
this is a very useful recognition, since it implies the correct things
about assignment and parameter-passing.
I believe most of us here try to follow Knuth's lead and use
'parameter' for the local names and 'argument' for the value/object
that gets associated with the name.
Fine with me. (I've also seen "formal parameter" and "actual
parameter" respectively, but hey, I'm flexible.)
Python's assignment *statement* does what we routinely do in
everyday life when we assign new labels to things, whether
permanently or temporarily.
Super, that's great, but not very helpful, at least to someone who
knows any other programming language. For them, it's better to point
out that it does what those other languages routinely do when they
assign an expression to an identifier.
>I wonder if that could be tested systematically. Perhaps we could
round up 20 newbies, divide them into two groups of 10, give each
one a 1-page explanation either based on passing object references
by-value, or passing values sort-of-kind-of-by-reference, and then
check their comprehension by predicting the output of some code
snippets. That'd be very interesting.

Except for your garbling of the alternative to your version, I agree.
I suspect that different people might do better with different
explanations, depending on background.
Could be.

Maybe we could run such an experiment at PyCon, pulling in non-
attendees from the hallway and getting them to take the test in
exchange for a free donut or coffee.

Best,
- Joe

Nov 7 '08 #139
On Nov 7, 2008, at 12:35 PM, Terry Reedy wrote:
http://en.wikipedia.org/wiki/Call_by...all_by_sharing

Call by sharing

Also known as "call by object" or "call by object-sharing" is an
evaluation strategy first named by Barbara Liskov et al for the
language CLU in 1974[1]. It is used by languages such as Python[2]
and Iota and (as argued by some[3]) Java, although the term is not
in common use by the Java community. Call-by-sharing implies that
values in the language are based on objects rather than primitive
types.

The semantics of call-by-sharing differ from call-by-reference in
that assignments to function arguments within the function aren't
visible to the caller (unlike by-reference sematics). However since
the function has access to the same object as the caller (no copy is
made), mutations to those objects within the function are visible to
the caller, which differs from call-by-value semantics.

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.
You know, people rip on Wikipedia, but I'm often surprised at how
frequently it succinctly and accurately describes a topic, even when
it is a topic of much controversy. The above summary seems spot on.
My difficulty, I guess, is that I'm coming from the Java/VB/RB
community, where the semantics are exactly the same as Python, and
where it makes perfect sense to call it call-by-value (since it is a
trivial generalization of the very same evaluation strategy used on
other types). But I get here, and there is widespread use of this
call-by-sharing term (though my initial impressions were much more
disparate and confusing than the above concise summary makes it sound).

Thanks for pointing this out. I'd only found the entry on evaluation
strategies, which makes no mention of call-by-sharing.
http://www.pmg.csail.mit.edu/papers/...ef/node34.html

Call by Sharing
The caller and called routine communicate only through the argument
and result objects; routines do not have access to any variables of
the caller.

After the assignments of actual arguments to formal arguments, the
caller and the called routine share objects. If the called routine
modifies a shared object, the modification is visible to the caller
on return. The names used to denote the shared objects are distinct
in the caller and called routine; if a routine assigns an object to
a formal argument variable, there is no effect on the caller. From
the point of view of the invoked routine, the only difference
between its formal argument variables and its other local variables
is that the formals are initialized by its caller.

==========================
Python object *do* have access to surrounding scopes, but the second
paragraph exact described Python, as does the corresponding
Wikipedia entry.
Well yes, but it exactly describes VB.NET, RB, Java, and C++ as well
(when talking about object types rather than primitive types).
==================================
myweb.lmu.edu/dondi/fall2004/cmsi585/subroutines-in-depth.pdf

• Call by sharing
– Used by languages where variables are already references to objects
– Parameters are references to objects, but assignments to those
parameters
don’t change them at the level of the caller — e.g. Java uses call-
by-value
for primitives (int, char) and uses call-by-sharing for Objects
Well, not according to the Java specification, it doesn't. But these
sources finally make it clear that "call-by-sharing" is just a special
case of call-by-value when the value is an object reference. So, it's
accurate to say that Java (and all the other languages under
discussion) always use call-by-value, but some of those calls
(depending on the parameter data type) may also be described as call-
by-sharing.

I suppose it's reasonable that if you use a language where some types
are references and some types are not, the simplest thing is to
describe all calls as call-by-value (except for those with an optional
by-reference syntax, like C++ and RB/.NET). But if you come from a
language where all types are references, then it's reasonable to
describe all calls as call-by-sharing (provided the language doesn't
also support call-by-reference).

So. How about this for a summary?

"Python uses call-by-sharing. That's a special case of call-by-value
where the variables are references to objects; it is these references
that are copied to the parameters, not the objects themselves. For
users of other languages, this is the same semantics used for objects
in Java, RB/VB.NET, and C++ when dealing with objects."

Best,
- Joe

Nov 7 '08 #140
Joe Strout <jo*@strout.netwrites:
So. How about this for a summary?

"Python uses call-by-sharing. That's a special case of call-by-value
where the variables are references to objects; it is these references
that are copied to the parameters, not the objects themselves. For
users of other languages, this is the same semantics used for objects
in Java, RB/VB.NET, and C++ when dealing with objects."
Here's a story about call by sharing:

One day a black cat came strolling into our garden. It seemed quite
hungry so we gave it some milk and food remains. The cat drank the milk
and ate the food, stayed for a bit then walked away. A couple of days
later it came back, miaowing, so we fed it again. It started coming to
see us almost every day, sometimes sleeping in the house, sometimes
disappearing for a day or two. We started thinking of it as our cat and
we *named* it Napoleon. Napoleon became very popular and stayed at home
more and more often, and very young son was very fond of it, calling it
something like 'Polion'.

Unfortunately Napoleon got infested with fleas and we had to take him to
the vet. The vet scanned Napoleon with a little machine and discovered
that it had an ID chip. This revealed that Napoleon was really called
Nelson (ironically!) and belonged to a house down our road. We
contacted them and they were happy to 'share' the cat with us. By this
time the cat answered to the name of Napoleon so we carried on calling
it this name.

This story ends quite sadly. One day Napoleon escaped out the front
door and got run over by a passing van. Our son kept asking for Polion
so we decided to get a new cat and called him Napoleon as well (we
decided it would be easier for him!).

Now some questions about the story:

1. Is Napoleon a copy of Dobby or are they the same cat?

2. Is Polion a copy of Napoleon or are they the same cat?

3. When we got rid of Napoleon's fleas, was Nelson deflea-ed as well?

4. When Napoleon died, did Nelson die as well?

5. When we got a new Napoleon, does this mean that our neighbours got a
new Nelson?

Now a question about the questions about the story:

To be able to understand the story and answer questions 1-5, do we
need to think of Napoleon, Nelson and Polion as variables containing
references to cat objects, or is it enough to think of them as three
names for cats?

--
Arnaud
Nov 7 '08 #141
Joe Strout wrote:
On Nov 7, 2008, at 12:13 PM, Terry Reedy wrote:
[...]
>>I wonder if that could be tested systematically. Perhaps we could
round up 20 newbies, divide them into two groups of 10, give each one
a 1-page explanation either based on passing object references
by-value, or passing values sort-of-kind-of-by-reference, and then
check their comprehension by predicting the output of some code
snippets. That'd be very interesting.

Except for your garbling of the alternative to your version, I agree.
I suspect that different people might do better with different
explanations, depending on background.

Could be.

Maybe we could run such an experiment at PyCon, pulling in non-attendees
from the hallway and getting them to take the test in exchange for a
free donut or coffee.
+1: great idea! It would make a good video too ...

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 7 '08 #142
On Nov 7, 3:03*pm, Arnaud Delobelle <arno...@googlemail.comwrote:
Joe Strout <j...@strout.netwrites:
So. *How about this for a summary?
"Python uses call-by-sharing. *That's a special case of call-by-value
where the variables are references to objects; it is these references
that are copied to the parameters, not the objects themselves. *For
users of other languages, this is the same semantics used for objects
in Java, RB/VB.NET, and C++ when dealing with objects."

Here's a story about call by sharing:

One day a black cat came strolling into our garden. *It seemed quite
hungry so we gave it some milk and food remains. *The cat drank the milk
and ate the food, stayed for a bit then walked away. *A couple of days
later it came back, miaowing, so we fed it again. *It started coming to
see us almost every day, sometimes sleeping in the house, sometimes
disappearing for a day or two. *We started thinking of it as our cat and
we *named* it Napoleon. *Napoleon became very popular and stayed at home
more and more often, and very young son was very fond of it, calling it
something like 'Polion'.

Unfortunately Napoleon got infested with fleas and we had to take him to
the vet. *The vet scanned Napoleon with a little machine and discovered
that it had an ID chip. *This revealed that Napoleon was really called
Nelson (ironically!) and belonged to a house down our road. *We
contacted them and they were happy to 'share' the cat with us. *By this
time the cat answered to the name of Napoleon so we carried on calling
it this name.

This story ends quite sadly. *One day Napoleon escaped out the front
door and got run over by a passing van. *Our son kept asking for Polion
so we decided to get a new cat and called him Napoleon as well (we
decided it would be easier for him!).

Now some questions about the story:
Sorry didn't read above yet.
1. Is Napoleon a copy of Dobby or are they the same cat?
Same cat.
2. Is Polion a copy of Napoleon or are they the same cat?
Same cat.
3. When we got rid of Napoleon's fleas, was Nelson deflea-ed as well?
Yes.
4. When Napoleon died, did Nelson die as well?
No, honey. He lives on in all of us.
5. When we got a new Napoleon, does this mean that our neighbours got a
* *new Nelson?
No, darling, Nelson is just sleeping. When we got a New Orleans,
where did the old one go?
Now a question about the questions about the story:

* *To be able to understand the story and answer questions 1-5, do we
* *need to think of Napoleon, Nelson and Polion as variables containing
* *references to cat objects, or is it enough to think of them as three
* *names for cats?
I think they are names, implying that Python has a different "variable
model" than C++.

However, a[0] isn't exactly a name, per se, and if you say that 'b'
and 'a[0]' are names of an object, then 'a[1-1]', 'a[2*0]', etc. are
all names of it. Furthermore, some class models variables like this:

a.b= 'abc'
a.c= 'def'
a.d= 'ghi'

It also allows index access: a[0], a[1], a[2], respectively. 'abc'
has two names: 'a.b', and 'a[0]'. Correct?

Nov 7 '08 #143
Aaron Brady <ca********@gmail.comwrites:
Furthermore, some class models variables like this:

a.b= 'abc'
a.c= 'def'
a.d= 'ghi'

It also allows index access: a[0], a[1], a[2], respectively. 'abc'
has two names: 'a.b', and 'a[0]'. Correct?
You know very well that a.b and a[0] aren't names, they are function
calls written in short hand ;)

a.b is getattr(a, 'b')
a[0] is getattr(a, '__getitem__')(0)

So they just return an object, which happens to be the same :)

--
Arnaud
Nov 7 '08 #144
Joe Strout <jo*@strout.netwrites:
As for where I get my definitions from, I draw from several sources:

1. Dead-tree textbooks
You've been reading the wrong textbooks. Read Liskov -- she's called
CLU (and hence Python's) calling strategy "call-by-sharing" since the
70s.
2. Wikipedia [2] (and yes, I know that has to be taken with a grain of
salt, but it's so darned convenient)
3. My wife, who is a computer science professor and does compiler
research
4. http://javadude.com/articles/passbyvalue.htm (a brief but excellent
article)
5. Observations of the "ByVal" (default) mode in RB and VB.NET
6. My own experience implementing the RB compiler (not that
implementation details matter, but it forced me to think very
carefully about references and parameter passing for a very long time)

Not that I'm trying to argue from authority; I'm trying to argue from
logic. I suspect, though, that your last comment gets to the crux of
the matter, and reinforces my guess above: you don't think c-b-v means
what most people think it means. Indeed, you don't think any of the
languages shown at [1] are, in fact, c-b-v languages. If so, then we
should focus on that and see if we can find a definitive answer.
I'll give you the definitive answer from a position of authority,
then. I took Barbara Liskov's graduate-level class in programming
language theory at MIT, and she called what Python does
"call-by-sharing".

|>oug
Nov 8 '08 #145
Joe Strout <jo*@strout.netwrites:
Yes, OK, that's great. But there are several standard pass-by-
somethings that are defined by the CS community, and which are simple
and clear and apply to a wide variety of languages. "Pass by object"
isn't one of them.
"Call-by-sharing" *is* one of them, and the term has been around since
the 70s:

http://hopl.murdoch.edu.au/showlanguage.prx?exp=637
I guess if you want to campaign for it as a shorthand for "object
reference passed by value," you could do that, and it's not
outrageous.
There's no need for a campaign. The term has already been used in the
academic literature for 34 years.
But to anybody new to the term, you should explain it as exactly
that, rather than try to claim that Python is somehow different from
other OOP languages where everybody calls it simply pass by value.
It's not true that "everybody calls it simply pass by value".
OK, if there were such a thing as "pass-by-object" in the standard
lexicon of evaluation strategies, I would be perfectly happy saying
that a system has it if it behaves as though it has it, regardless of
the underpinnings.
There is "call-by-sharing" in the standard lexicon of evaluation
strategies, and it's been in the lexicon since 1974.
However, if you really think the term is that handy, and we want to
agree to say "Python uses pass by object" and answer the inevitable
"huh?" question with "that's shorthand for object references passed by
value," then I'd be OK with that.
Excellent. We can all agree to get along then!

|>oug
Nov 8 '08 #146
On Nov 7, 3:39*pm, Arnaud Delobelle <arno...@googlemail.comwrote:
Aaron Brady <castiro...@gmail.comwrites:
*Furthermore, some class models variables like this:
a.b= 'abc'
a.c= 'def'
a.d= 'ghi'
It also allows index access: a[0], a[1], a[2], respectively. *'abc'
has two names: 'a.b', and 'a[0]'. *Correct?

You know very well that a.b and a[0] aren't names, they are function
calls written in short hand ;)

a.b * is * getattr(a, 'b')
a[0] *is * getattr(a, '__getitem__')(0)

So they just return an object, which happens to be the same :)

--
Arnaud
Therefore objects don't need names to exist. Having a name is
sufficient but not necessary to exist. Being in a container is
neither necessary -nor- sufficient.

a is the name of an object. The object is associated with a
dictionary you can usually access. 'b' is a key in the dictionary.
Nov 8 '08 #147
Steven D'Aprano wrote:
Python's behaviour is not the same as what
Pascal, or C, calls call-by-value.
Python's assignment is not the same as what Pascal or C calls
assignment, either. Yet we don't hear anyone claim that the
term "assignment" shouldn't be used in Python.

The difference between call-by-value in Python and Pascal is
exactly the same difference as there is between assignment
in Python and Pascal. Why should we throw out one term but
not the other?

--
Greg
Nov 8 '08 #148
On Fri, 07 Nov 2008 13:05:16 -0700, Joe Strout wrote:
In Python, AFAICT, there is only one type, the object reference. So,
the type of every variable is 'reference', and each one contains a
reference.
This is wrong. If we take "variable" to mean "name", then Python names do
not have types. But *objects* have types, and there are many of them:
>>a = 23; type(a)
<type 'int'>
>>a = "foo"; type(a)
<type 'str'>
>>a = []; type(a)
<type 'list'>

But a name that isn't bound to an object doesn't have a type:
>>del a; type(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

The type information is associated with the object, not with the name.

It is possible that, in the C implementation, there is a C-type
'reference' and all(?) C variables relating to the implementation of
namespaces have that type. Possibly. But even if true, that's the wrong
level of description.
--
Steven
Nov 8 '08 #149
On Sat, 08 Nov 2008 17:12:00 +1300, greg wrote:
Steven D'Aprano wrote:
>Python's behaviour is not the same as what Pascal, or C, calls
call-by-value.

Python's assignment is not the same as what Pascal or C calls
assignment, either. Yet we don't hear anyone claim that the term
"assignment" shouldn't be used in Python.
Er, you're not from around here are you?

I admit that sometimes I slip into bad habits, but generally the accepted
terminology is that x = 1 binds the object 1 to the name x.

The difference between call-by-value in Python and Pascal is exactly the
same difference as there is between assignment in Python and Pascal. Why
should we throw out one term but not the other?
Exactly.

--
Steven
Nov 8 '08 #150

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Liming | last post by:
Hello all, I have a custom class object with some prototype methods like setKeyDownEvent, etc. The problem is on my webpage, after I instantiate the class, I try to do .addEventLister() to a...
7
by: Brad Baker | last post by:
I am trying to programmatically set a placeholder control in csharp which is nested inside a repeater control between <ItemTemplateand </ItemTemplate> tags, however I am running into problems. I've...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.