[Edu-sig] Pass by Reference

Michael H. Goldwasser goldwamh at slu.edu
Tue May 20 19:25:48 CEST 2008


As much as I know that I should stop flaming the fires, I'd like to
jump in with some of my own thoughts on the recent thread.

John Zelle and I have been somewhat cast as on opposite extremems.  If
you look at the pictures we draw for students to explain parameter
passing and function calls, they are inherently the same. 

Python's model is very self-consistent and quite straightforward to
explain to beginners.  As I've said in an earlier post, everything
comes down to understanding what an assignment statement does.  Well
before discussing functions, it is important for students to
understand the semantics of

x = 5
y = x
x = 6
print y   # still bound to 5

This is the issue that must be explained to students well before they
broach the topic of functions.  Yet once the assignment semantics is
understood, the passing mechanism is a straightforward application of
the assignment statement FORMAL = ACTUAL.


Its the surrounding discussion that differs.  We seem to be completely
bogged down in the debate over the "call-by-value" and
"call-by-reference" terminology.  Part of the problem is that I don't
believe there is a consistent, canonical source for definitions.

On issue is whether this terminology is meant to describe purely the
semantics of a programming language or to describe the internal
implementations.  This is the very first issue raised in the section
on parameter passing in the Noonan/Bynum chapter of The Computer
Science and Engineering Handbook (ed. Tucker).  You could presumably
draw a different conclusion depending on whether the focus is
semantics or implementation.  I certainly think that for the laymen,
the verbs "call" and "pass" are more suggestive of the runtime
implementation.

Another problem is the hangup on a viewing a variable as a classic
named memory slot, which simply is not the case in Python.  When
passing an argument, the issue in applying the verbs is the IMPLICIT
object of that verb, that is WHAT IS BEING PASSED?  If we cannot agree
on what we're passing then we cannot agree on how it is passed.

John has made the case that the "value" of a variable is an implicit
REFERENCE, and therefore that a copy of that "value" is being passed.
I disagree with forcing this characterization upon students (or
programmers).  Those references are not a tangible entity of the
language, but an internal implementation detail in some sense.

I am of the view that the "value" of a variable is the underlying
object to which it is bound.  Namespaces enforce a mapping from
identifiers to objects.  When I make a call to paint(foo), I consider
the argument to be that object currently referenced by the name foo.
So then the question arises how that object is communicated upon the
call of a function.  In this regard, I think we all agree that the
information (i.e., the object) is being passed by reference rather
than by value.


A few other technical objections:

  * If we go back to the issue of what is placed on the runtime call
    stack, consider even a basic call sqrt(42).  In a classic
    call-by-value language, I would reasonably expect for the binary
    representation of the value 42 to be placed on the call stack as
    the form of communication.  With call-by-reference I would
    reasonably expect for the bits on the call stack to be an indirect
    reference to some memory location at which the value 42 is stored.

    In Python, this number will be passed at runtime as an indirect
    reference, not as 0000000000101010.   The same is true if I make a
    call to data.append(sqrt(42));   the calling mechansim will not be
    placing the floating-point value on the call stack but rather a
    reference to an (unnamed) object that was the result of the nested
    call.

    I have a hard time seeing any reason for portraying this as call-by-value.


  * In many of the languages being discussed, the issue is that a
    variable is a (name,memory) binding where bits are stored in
    memory and the name is used syntactially to access those bits
    (with this mapping typically performed at compile time)

    This is not even the mechanism in Python.  An identifier is a
    string.  There is no specific memory address associated with than
    name that is used to store a pointer as its value. The identifiers
    in the namespace are strings that serve as dictionary keys, and
    those are mapped by the dictionary to those underlying pointers.

    Arguments portraying the by-value vs. by-reference argument as a
    simple test of wheter calling bar(x) allows the function to change
    the "value" of variable x, where value is thought of as this
    implicit pointer are misguided.  John writes:

    >    As I keep explaining, when the term pass-by-reference is applied to
    >    parameter passing, it means that the formal parameter becomes a
    >    reference to the actual variable used in the argument (more technically,
    >    the formal parameter name is bound to the storage location of the
    >    argument variable). That means changes to the value of the formal
    >    parameter actually change the contents of the calling variable. Python
    >    does not do this! You can change the state of the object that's referred
    >    to, but you _cannot change the contents of the variable_ (what it refers
    >    to).

    Even in the classic call-by-reference of the C++ example

    void bar(int &formal) {
       formal++;
    }

    A call to bar(x) cannot change the binding for the caller's
    variable x.  It refers to a particular memory slot and the callee
    can not change that binding.  The callee simply has access to
    alter the bits that are stored in that slot.  Paraphrasing John's
    own words, you can change the state of the data that the name x
    refers to but you cannot make the name x refer to something else.

    I would say that Python meets the criteria that "the formal
    parameter name is bound to the storage location of the argument"
    if we were to agree to the fact that the argument is the
    underlying object (not the identifier that I presume John has in
    mind when he wrote "argument variable").


  On that note, I'll join in support of John's conclusion:

      "OK, now I'm letting go of the issue."

With regard,
Michael

       +-----------------------------------------------
       | Michael Goldwasser
       | Associate Professor
       | Dept. Mathematics and Computer Science
       | Saint Louis University
       | 220 North Grand Blvd.
       | St. Louis, MO 63103-2007



More information about the Edu-sig mailing list