By value or by reference?

Alex Martelli aleaxit at yahoo.com
Tue Oct 19 02:38:55 EDT 2004


On 2004 Oct 18, at 22:46, Josiah Carlson wrote:
    ...
>
> I agree with most everything you have said, though consider the pointer
> vs. value of C to define the semantics of the passing.  That is, if you
> get a pointer in C, it is by reference.  If you don't get a pointer, it
> is by value.

I disagree: you get the value of the pointer.  If you assign to the 
barename of the pointer, this has no effect on the caller.

void foo(int* x) {
     x = 0;
}

the fact that x is a pointer makes no difference whatsoever: the x=0; 
within function foo is just assigning to local variable 'x', without 
any effect on the caller, just as if the signature was '(int x)' 
instead.

"By reference" semantics, in e.g. Fortran, Visual Basic, Pascal, C++, 
..., are normally taken to mean that the function can do:
     x = 0;
i.e. assign to the barename of an argument, and thereby affect the 
caller.  In Fortran (traditionally) it's always that way (the language 
definition supports both value/return and reference semantics, with 
lots of strictures on what is semantically correct in order to ensure 
both mechanisms work; in practice, implementations for the last 30+ 
years have used references, 99% of Fortran programmers are unaware of 
the strictures, and get big surprises when an aggressive optimizer, 
taking advantage of the constraints the programmers routinely violate, 
turns their code into mush;-).  In Pascal, defining an argument in the 
signature as "x:integer" or "var x:integer" makes all the difference; 
in Visual Basic, the adjectives Byval and Byref do; in C++, the 
referencemarker ampersand ('int&x' in the signature); etc.

C has nothing like that.  You can explicitly take the address of 
something, you can pass (by value!) an address ('pointer'), you can 
dereference an address -- and these are the mechanisms you can use to 
get PAST the lack of byref parameters.  The workarounds in Fortran for 
the lack of byval parameters are sometimes even funnier: you see X+0 
passed as the actual argument, for example, or sometimes X*1, in the 
hope that this will make a copy of X and thereby preserve X from 
modification (the interested reader can study the Fortran 66 and 77 
manuals to see how this tricks have  fared, standardswise... compilers 
often are more accomodating than the standards, though in the Fortran 
world optimization is SO crucial that this need not be so...).
[[similar tricks in Python are using L[:], L+[], or L*1, to get a copy 
of L -- less forgivable in Python where list(L) does that cleanly, 
explicitly and legibly, of course;-)]]

>
> I also agree that everything is pure and explicit in both languages, it
> took me a few minutes mucking around with the interpreter my first time
> to understand how Python deals with the base types.
>
> I'm trying to point out that if you toss the standard C semantic
> definition of "pass by value" and "pass by reference", by merely
> pretending that the definitions have not been given in the history of
> computer science, and just look at how Python does actual name binding
> in namespaces/scopes, you can understand what Python does much better
> than to get into a "Python does pass by reference" vs. "Python does 
> pass
> by value" argument.

I agree.  But in C you cannot possibly do better than "C does pass by 
value, and assigns by value [with an unfortunate hack regarding arrays 
decaying to pointers]".  The concept of passing by reference is needed 
in other languages, but not in C (nor Python).  "Pass by value" 
normally (for most languages) implies a copy: once you realize that 
Python doesn't do implicit copies (the +[], *1 and [:] hacks 
notwithstanding, those ARE computing expressions after all) then 'pass 
by value' is in fact just as applicable to Python -- the difference is 
not in how arguments are passed, but in the fact that in Python a 
name's value is ALWAYS a reference to an object, so the value (that is 
passed) IS the reference (to the object), while in C variables are 
little boxes with their value inside, so the value that is passed is a 
copy of the box's contents (some of those boxes, known as pointers, 
hold addresses...).


Alex




More information about the Python-list mailing list