Finding the instance reference of an object

G

greg

Dennis said:
You must have missed all the threads about "binding" then... Wherein
a Python "assignment statement" "binds the LHS name to the RHS object"
rather than "assigns the RHS object value to the LHS"

I know that it is sometimes referred to that way. But
nobody seems to get worked up into a religious fervour
and insist that the word "assignment" be banned from the
Python terminology lexicon, the way some people seem to
do about words such as "value" and "reference".

If we can all get along nicely and accept that "assignment"
is an acceptable term, among alternatives, for something that
has an analogy, if not an exact equivalent, in other languages,
why can't we do the same for "reference" and "call by value"?
 
A

Arnaud Delobelle

greg said:
It's a reference to a variable. It's what gets passed behind
the scenes when you use a VAR parameter in Pascal, or a
ByRef parameter in VB.

Do you mean you can't do the following C++ snippet in Pascal or VB? I
haven't used Pascal for more than 20 year and I have never used VB, so
this is a real question.

foo(int &x) {
x = 7;
}

struct bar {
int i;
float j;
};

int main() {
int a[10];
bar b;
// What is passed to foo below is obviously not a 'variable
// reference' as the argument is not a variable.
foo(a[3]); // Now a[3] == 7
foo(b.i); // Now b.i == 7
}

[...]
Passing q by value means that the value of the expression 'q',
whatever that is in the language concerned, gets assigned to the
local variable 'p', whatever *that* means in the language concerned.

Because of the way C assignment works, the result is that p ends
up with a copy of the whole struct.

Because of the way Python assignment works, the result is that
p and q end up referring to the same object.

The difference is *entirely* due to the difference in the semantics
of assignment between the two languages. Once you've taken that
into account, there is no need to look for difference in the
parameter passing scheme.

I'm not sure that your definition of 'call by value' is widely
accepted. If it was, then this thread wouldn't exist.

I've tried to google for an authoritative definition but it's harder
than I thought. This definition comes up everywhere though.

call-by-value

(CBV) An evaluation strategy where arguments are evaluated before
the function or procedure is entered. Only the values of the
arguments are passed and changes to the arguments within the called
procedure have no effect on the actual arguments as seen by the
caller.

[This from http://dictionary.reference.com/browse/call-by-value]

It seems to me that it more or less is the definition that most people
on this thread has been implicitly using.
 
M

Marc 'BlackJack' Rintsch

greg said:
It's a reference to a variable. It's what gets passed behind the scenes
when you use a VAR parameter in Pascal, or a ByRef parameter in VB.

Do you mean you can't do the following C++ snippet in Pascal or VB? I
haven't used Pascal for more than 20 year and I have never used VB, so
this is a real question.

foo(int &x) {
x = 7;
}

struct bar {
int i;
float j;
};

int main() {
int a[10];
bar b;
// What is passed to foo below is obviously not a 'variable
// reference' as the argument is not a variable.
foo(a[3]); // Now a[3] == 7
foo(b.i); // Now b.i == 7
}

Translated to Pascal:

Program Test;

Type
Bar = Record
i: Integer;
j: Real;
End;

Var a: Array[0..9] Of Integer;
b: Bar;

Procedure Foo(Var x:Integer);
Begin
x := 7;
End;

Begin
Foo(a[3]);
WriteLn(a[3]); {Prints 7.}
Foo(b.i);
WriteLn(b.i); {Prints 7.}
End.

In "reality" I would not expect that anything is passed here but that the
compiler inlines it as direct assignment. Should read: Copying the bit
pattern of a 7 into the fixed memory locations. :)

Ciao,
Marc 'BlackJack' Rintsch
 
T

Terry Reedy

greg said:
No. Passing q by value means that the value of the expression 'q',
whatever that is in the language concerned, gets assigned to the
local variable 'p', whatever *that* means in the language concerned.

In other words, as I acknowledged in my other post, one can say that all
calling is calling by value.
 
G

greg

Arnaud said:
// What is passed to foo below is obviously not a 'variable
// reference' as the argument is not a variable.
foo(a[3]); // Now a[3] == 7
foo(b.i); // Now b.i == 7

Yes, it is. By "variable" I mean what C calls an lvalue,
i.e. something you can assign to.
I'm not sure that your definition of 'call by value' is widely
accepted. If it was, then this thread wouldn't exist.

It seems to be accepted by the Java and VB community,
judging by what they refer to as call-by-value in those
languages.

You won't necessarily find it written down anywhere in
the exact words I used. I have reverse-engineered it
from the characteristics of a wide variety of languages
that use the term call-by-value to describe one of their
parameter passing mechanisms. Think of it as a theory
that fits the observed linguistic facts.
(CBV) An evaluation strategy where arguments are evaluated before
the function or procedure is entered. Only the values of the
arguments are passed and changes to the arguments within the called
procedure have no effect on the actual arguments as seen by the
caller.

That hinges on what exactly is meant by "changes to
the arguments". In Python it can only mean assigning
directly to the bare name -- anything else isn't
changing the argument itself, but something else to
which the argument refers.
 
G

greg

Terry said:
In other words, as I acknowledged in my other post, one can say that all
calling is calling by value.

No, those are not other words for what I'm saying.
Call by reference is very demonstrably different
from call by value, as has been pointed out a large
number of times already.
 
T

Terry Reedy

greg said:
That hinges on what exactly is meant by "changes to
the arguments".

Mutating them, like Python does, which is why calling Python CBV leads
people to write buggy code.
>In Python it can only mean assigning
directly to the bare name -- anything else isn't
changing the argument itself, but something else to
which the argument refers.

Hogwash. The argument is the object and mutable objects can be changed
as seen by the caller.
 
J

Joe Strout

Mutating them, like Python does, which is why calling Python CBV
leads people to write buggy code.


Hogwash. The argument is the object and mutable objects can be
changed as seen by the caller.

By that definition, Java, REALbasic, C++, and VB.NET are all call-by-
reference too (even when explicitly using the "ByVal" keyword in RB/
VB.NET). This will come as quite a shock to the designers and users
of those languages.

For what it's worth, I think Greg (double-quoted above) has it exactly
right. The argument in any of these languages is an object reference;
changing the object and changing the object reference are two
different things.

Best,
- Joe
 
T

Terry Reedy

Joe said:
By that definition, Java, REALbasic, C++, and VB.NET are all
call-by-reference too (even when explicitly using the "ByVal" keyword in
RB/VB.NET). This will come as quite a shock to the designers and users
of those languages.

For what it's worth, I think Greg (double-quoted above) has it exactly
right. The argument in any of these languages is an object reference;
changing the object and changing the object reference are two different
things.
 
T

Terry Reedy

Joe said:
By that definition, Java, REALbasic, C++, and VB.NET are all
call-by-reference too (even when explicitly using the "ByVal" keyword in
RB/VB.NET). This will come as quite a shock to the designers and users
of those languages.

For what it's worth, I think Greg (double-quoted above) has it exactly
right. The argument in any of these languages is an object reference;

In the Python I am talking about, the language defined in the Python
Reference Manual, arguments are objects.

Bye,

tjr
 
A

Aaron Brady

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?

Do you ever say to someone, "'Napoleon' will no longer refer to
Nelson. It is this lobster now instead", while you are holding a
lobster?

My point is that the assignment operation is rare in natural language.

Some examples:

unitedstates.president= people['Barack Obama']
catholicchurch.pope= people['Joseph Ratzinger']
chicagocubs.manager= people['Lou Pienella']

That is, in January, 'The President' will start to refer to a
different person. But you don't see:

popstars['Britney Spears']= people['Ricky Martin']
people['Richard Nixon']= people['Ronald Reagan']

You also have expressions, such as 'the man in the corner drinking
Coke' and 'the first street on the right', which would not be likely
to be modeled as attributes, per se, such as:

corner.men.drinking['Coke']
street.ontheright[0]

You'd more likely use:

"select id from people where standingin = 'corner' and drinking =
'coke'"
"select id from streets where distanceonright =
min( distanceonright )"

Maybe in the future we'll see relational code, rather than
hierarchical subclasses:
'raise CannotFlyException'
 
A

Arnaud Delobelle

Aaron Brady said:
Do you ever say to someone, "'Napoleon' will no longer refer to
Nelson. It is this lobster now instead", while you are holding a
lobster?

Not explicitly. But in the course of conversation I might refer to
Napoleon, meaning Napoleon Bonaparte (1769 - 1821) or Napoleon III (1808
- 1873). There would then be an implicit 'rebinding' of the name Napoleon.
My point is that the assignment operation is rare in natural language.

My point was to get away from a model for Python which was built on its
likely implementation and to hint that we can build one using the naive
concept of 'name for a thing' instead. IOW, 'call by value' is an
unnecessary obfuscation of what *actually* happens (even though it may
describe accurately the artifacts employed by an implementation)

I'm glad that you thought about it!
 
A

Aaron Brady

Not explicitly.  But in the course of conversation I might refer to
Napoleon, meaning Napoleon Bonaparte (1769 - 1821) or Napoleon III (1808
- 1873).  There would then be an implicit 'rebinding' of the name Napoleon.


My point was to get away from a model for Python which was built on its
likely implementation and to hint that we can build one using the naive
concept of 'name for a thing' instead.  IOW, 'call by value' is an
unnecessary obfuscation of what *actually* happens (even though it may
describe accurately the artifacts employed by an implementation)

I'm glad that you thought about it!

I agree with Terry that all calling is call-by-value, and Steven that
all calling is call-by-bit-flipping. I agree with Joe that call-by-
object is a special case of call-by-value.

I thought of another way Python's passing method could be
implemented. Parameters are passed as namespace-name pairs, and every
time a variable occurs, it's looked up in the namespace it's in. If
it's changed (concurrently) in the outer scope, a copy is made into
the inner scope. If it's changed in the inner scope, a new entry is
added there.

It's still call-by-value (and bit-flipping) on some level, in the
trivial sense. What else is it?
 
J

Joe Strout

I agree with Terry that all calling is call-by-value, and Steven that
all calling is call-by-bit-flipping. I agree with Joe that call-by-
object is a special case of call-by-value.

Woo! Almost sounds like approaching consensus. :)

However, I'm sorry to say that I think both Terry's and Steven's
descriptions are unhelpful. There really are important distinctions
among parameter evaluation strategies. Call-by-reference is not call-
by-value (though it is call-by-bit-flipping, but that's too low a
level).

But if we can agree that call-by-sharing (which I believe is the more
widely documented term than "call-by-object") is a special case of
call-by-value, when the parameters are object references, then I think
we may have a winner.

Best,
- Joe
 
S

Steven D'Aprano

By that definition, Java, REALbasic, C++, and VB.NET are all call-by-
reference too (even when explicitly using the "ByVal" keyword in RB/
VB.NET).

No, they are not call-by-reference either. They are call-by-sharing, just
like Python and CLU.
 
S

Steven D'Aprano

That hinges on what exactly is meant by "changes to the arguments". In
Python it can only mean assigning directly to the bare name -- anything
else isn't changing the argument itself, but something else to which the
argument refers.

But the name isn't the argument. The argument to a function is an object,
not a name. You can't write a function in Python that takes a name as an
argument[1], which would be equivalent to Pascal's "var" parameters.

Take a function foo that takes one formal parameter x. Pass an actual
argument y to it. The argument is the object currently bound to y, not
the name y. Nothing inside foo can rebind the name y because foo doesn't
see the name y, it sees the object. Rebinding (or deleting) the name x
inside foo does nothing to the object bound to y, or the name y.






[1] You can pass a string representing the name to a function, which can
then use some combination of setattr, globals(), exec etc to work with
the name represented by that string. But you're still passing an object
to the function, not a name.
 
G

greg

Arnaud said:
But in the course of conversation I might refer to
Napoleon, meaning Napoleon Bonaparte (1769 - 1821) or Napoleon III (1808
- 1873).

That's more like referring to the name 'Napoleon' in
two different namespaces. The original binding still
exists, you're just switching contexts.
My point was to get away from a model for Python which was built on its
likely implementation and to hint that we can build one using the naive
concept of 'name for a thing' instead.

I don't believe it's possible to build any complete and
correct model of Python behaviour without including some
concept equivalent to a reference.

You can talk about names written on PostIt notes and
such like, but that only gets you a short way. It doesn't
easily handle names in different namespaces, or references
that exist without simple names, e.g. list and tuple
items. Trying to repair these deficiencies only leads to
increasingly bizarre and contrived mental pictures.

On the other hand, if you explicitly include the concept
of a reference from the beginning, everything is quite
clear and consistent.

In other words, the model should be as simple as possible
but no simpler. Leaving out references makes it too
simple.

Another point I'd like to make is that there is nothing
inherently low-level about the concept of a reference.
It doesn't have to be implemented as a memory address or
any other particular machine-level thing. It's possible to
talk about Python object references in a completely
implementation-independent way.

Also, just because you don't explicitly refer to them and
manipulate them at the language level doesn't mean they
don't exist. To think otherwise is like thinking that air
doesn't exist just because you can't see it. There are
plenty of experiments which clearly indicate its existence.
Likewise, there are plenty of experiments that you can
perform with any Python interpreter that reveal the
existence of references, or something equivalent to them.
 
G

greg

Aaron said:
I thought of another way Python's passing method could be
implemented. Parameters are passed as namespace-name pairs, and every
time a variable occurs, it's looked up in the namespace it's in. If
it's changed (concurrently) in the outer scope, a copy is made into
the inner scope. If it's changed in the inner scope, a new entry is
added there.

That sounds like a kind of copy-on-write. It's certainly not
call-by-value by any sane interpretation (contrary to your
assertion that "all calling is call-by-value").
 
G

greg

Steven said:
But the name isn't the argument. The argument to a function is an object

The *formal* argument *is* a name, and that's what
the phrase "changes to the arguments within the called
procedure" is talking about.
Take a function foo that takes one formal parameter x. Pass an actual
argument y to it. The argument is the object currently bound to y, not
the name y. Nothing inside foo can rebind the name y because foo doesn't
see the name y, it sees the object.

More to the point, it sees the *name x* rather than the
name y, and rebinding the name x doesn't change the binding
of name y. Therefore, the name y has been passed by value,
not by reference.
[1] You can pass a string representing the name to a function, which can
then use some combination of setattr, globals(), exec etc to work with
the name represented by that string.

This would be the Python equivalent of the strategy used
in C to emulate call-by-reference -- and it's needed for
the same reason, i.e. the language itself only provides
call-by-value. So you pass a value that you can manually
dereference to get the same effect.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top