[Edu-sig] Pass by Reference

John Zelle john.zelle at wartburg.edu
Thu May 22 00:17:40 CEST 2008


Hi David,

I gave a detailed description of my definitions in a post a while back.
In that, I referred to the traditional view of a variable as a named
location. As per your request:

In call-by-value the formal parameter is a local variable whose content
is initialized with a copy of the value of the actual parameter.
Assignment to the formal parameter has no effect on the actual
argument. 

In pass by reference, the formal parameter is a name bound (by
reference) to the variable used as the argument of the call. In this
case, assignment to the formal parameter actually changes what is stored
in the caller variable.

On Wed, 2008-05-21 at 08:41 -0700, David MacQuigg wrote:
> Hi John,
> 
> I think what we all agree on is the details of what is happening in
> Python.  As long as we use unambiguous words to describe that process,
> there is no problem.  The problem is in the definition of
> "call-by-value".  I have offered a simple definition, what I called
> the "traditional" definition, but perhaps that is claiming too much
> priority for one tradition.  I'll call it the "common" definition,
> what most programmers will tell you, and what you find at
> http://en.wikipedia.org/wiki/Call_by_value

I'm using the exact same definition of call-by-value as you find in this
wikipedia entry. The difference between your view and mine does not turn
on the definition of call by value, but rather on what constitutes the
"value" of the expression. 

I'm saying it's clean, simple, and correct to say the result of an
expression in Python is a reference to some object. And that reference
is what is stored into a variable (which is then still just a named
location). You're saying the value of the expression _is_ the object. In
your view then, variables contain objects. I often speak along those
lines with Python, but in terms of defining the semantics of languages,
I think it's cleaner to say that Python variables contain references.
That way the term "variable" means the same thing for virtually every
language (Prolog notwithstanding). And all of the historical terms still
work just fine. In addition, if you look at the Python interpreter, I'm
sure there are references (addresses) to these heap-allocated objects
running around all over the place, for example in the runtime
stack-frames. What do you call the locations that contain those
references, if not "variables." That's certainly what they've been
called in the traditional programming languages literature for decades
now.

As for the wikipedia entry on call-by-reference, I find it too ambiguous
to say much about, but I can certainly make the case that it agrees with
me. What is an "implicit reference to the argument?" In the "canonical"
call by reference languages such as FORTRAN and Pascal, the argument to
the call has to be a variable (C++ lifts this restriction). The formal
parameter then becomes an alias for the same memory location as the
argument variable. In essence the formal parameter is a variable that
still lives in the caller's stack frame. This is achieved by passing the
variable's address "behind the scenes," and the language then specially
and automatically dereferences the address to manipulate the non-local
variable. That, to me, is call by reference. The reference is being sent
_implicitly_ and the language does something special to make it all
work. In other words, I reserve the term pass-by-reference as a name for
this specific language mechanism, not as a generic term for passing
references around in programs. You can pass references around in
(virtually) any language, regardless of what parameter passing mechanism
the designers provide. As I've pointed out before, I can pass references
(pointers) around in Pascal without ever using the pass-by-reference
mechanism that's built into the language. And I will have the "visible
side-effects" that result from aliasing. But that is not
pass-by-reference semantics.

In the case of Python, the references are _explicit_. The interpreter
doesn't do anything special or different behind the scenes at function
call time to grab the address of the argument. All Python variables
contain references, and expressions evaluate to references. The
parameter passing mechanism just copies the value of the reference from
the caller's variable into the formal parameter. The formal parameter is
still a local variable in every sense. You know this to be true, because
reassigning it has no effect in the caller.

I notice that the Wikipedia article tries to have it both ways by saying
Java is a "call-by-value language" but "frequently displays call by
reference semantics." But there are not two different mechanisms in
Java. The _mechanism_ is call-by-value. The call always happens in
exactly the same way regardless of the argument type. It just so happens
that when the argument is a reference to something mutable, then changes
to that mutable thing are visible to the caller, just as in Python,
Pascal (non VAR params), C, and any other call-by-value language that
allows variables to contain references to heap-allocated objects. 

By the way, the _lack_ of call-by-reference or a way to simulate it in
Java is, to my mind, a design flaw, as it leaves no straightforward
mechanism for a function to return multiple values. This is not an issue
in Python, which has multiple return values (well, packs and unpacks
tuples automatically).

I don't know if this helps clarify my position or not. But you asked...

--John

ps. Here's my acid test. A call-by-reference mechanism allows me to
define a swap function:

>>> a = 3
>>> b = 5
>>> swap(a,b)
>>> a
5
>>> b
3

Show me a Python function that does that and I'll gladly say it has
pass-by-reference semantics (or copy-restore :-).
> 

-- 
John M. Zelle, Ph.D.             Wartburg College
Professor of Computer Science    Waverly, IA     
john.zelle at wartburg.edu          (319) 352-8360  



More information about the Edu-sig mailing list