Aaron Brady wrote:
Possible compromise. You can think of functions as mutation-only.
You pass the object, and it gets a new (additional) name. The old
name doesn't go in. </compromise>
That's correct. The reference itself is passed in, not the variable (or
expression) that held or generated the reference in the calling code.
This is no different from, in C, passing an integer:
void foo(int bar) {
bar = 42;
}
int baz = 0;
foo(baz);
This doesn't change baz because, speaking precisely, baz wasn't passed
to foo -- only the *value* of baz (i.e. 0) was passed to foo. Within
foo, that value was stored in bar. Assigning a new value to bar does
not affect foo.
It's the exact same thing when the value happens to be a reference to an
object:
typedef SomeClass* SomeClassPtr;
void foo(SomeClassPtr bar) {
bar = new SomeClass();
}
SomeClassPtr baz = NULL;
foo(baz);
Again, we're not passing baz into foo; we're passing the *value* of baz
(i.e. NULL) into foo. That value is stored in bar within foo, and when
we assign a new value (a reference to a freshly minted SomeClass object)
into bar, of course it doesn't affect baz.
Regardless, IMO, references don't add any explanatory power; they just
make you feel cocky that you know what they are.
Nonsense. They are the simple and clear explanation of what's going on.
M: If 'fun()' returned a reference, you would be able to assign to it.
m: You can't assign to it.
C: It doesn't return a reference.
C is false because M is false (at least, in the way I believe you mean
it). Or, more precisely, both M and m are nonsensical; what does it
mean to "assign to a reference"? It makes no sense. What would it mean
to assign to 42?
You don't assign to references any more than you assign to integers or
assign to strings or assign to None. Those are all values, and you
don't assign to values -- you assign to variables. "Assign" means to
give a new value to a variable, i.e. to let (or cause) a variable to
have a new value. (Ye olde BASIC even used the LET keyword to indicate
this, e.g. LET X = 42.) Speaking casually, we don't always make this
distinction, but I think precision is needed here.
So, I see two ways to make sense of your argument:
M1: If 'fun()' returned a variable, you would be able to assign to it.
m1: You can't assign to it.
C1: It doesn't return a variable.
This is true. (Technically, instead of variable, we should say "LValue"
here -- there are things slightly more complex than simple variables
that can serve as the left-hand side of an assignment. So replace
"variable" with "lvalue" above if you prefer.)
Or, the other way some may see it is:
M2: If 'fun()' returned a reference, you might be able to mutate the
object that refers to.
m2: You can sometimes mutate the object it refers to.
C2: 'fun()' returns a reference.
This is true (though the logic is flawed, but fixable).
-- Why can't I assign to a function call?
-- Python variables are references only.
-- Ok, why can't I assign to a function call?
You're right, "Python variables are references only" has nothing to do
with it. In a language where the only data type were "integer", you
wouldn't be able to assign to a function call either.
You can't assign to a function call because a function call is not
itself an lvalue, and it doesn't return an lvalue. That's just not
something you can get for free from the type model; it's an extra
feature that would have to be built into the language somehow, and
Python doesn't have it.
If assignment were an operator rather than a statement, and could be
overridden in a class via some specially-named method -- or, for that
matter, if the assignment statement looked for such a method when it
finds an object reference on the left-hand side -- then any object could
be an lvalue, and you COULD (in some cases) assign to the result of a
function. But it's not and it doesn't.
Best,
- Joe
--
http://mail.python.org/mailman/listinfo/python-list