Guide to the python interp. source?

Alex Martelli aleax at aleax.it
Sat Jul 27 10:50:52 EDT 2002


Tim Gahnström /Bladerman wrote:

> 
> "Terry Reedy" <tjreedy at udel.edu>
>> > Things I want to change is for example, everything should be "call
>> > refferense",
>>
>> It already is, which is why functions can mutate mutable objects.
>> (This surprises some beginners.)  Of course, for immutables (numbers,
>> strings, tuples), there is no semantic difference between reference
>> and value passing except for reduced memory usage.
> 
> I want to make all variables mutable.

Variables are just names, "post-it" tags that ate weakly attached
to an object at any given time.  They could (perverting terms) be
said to be "mutable" in that nothing forbids detaching the post-it
from one object and attaching it to another one (or just detaching
it, that's what the del statement is for).

If by "variables" you also want to mean structured names, i.e,
x.y to mean attribute y of object x, right now it's up to x's type
if attribute y is 'mutable' (reattachable, detachable, attachable
at all).  x's type may define for the purpose methods named
__setattr__ and __delattr__, or in Python 2.2 "properties" (and
potentially other descriptors) that defines what it means to try
to attach an object to the name x.y.  When x's type is a class and
does not do anything about it, by default x carries around a dict
and x.y is 'mutated' by acting on x.__dict__['y'].

But the mutable/nonmutable distinction normally applies to OBJECTS.
Python, like Java, uses nonmutable strings for the simplicity and
clarity they bring (but Python was there first, just as it was for
the "reference semantics" above summarized... well, not _first_, but
definitely before Java:-).

Don't confuse *mutating an object* with *reattaching a name to a
different object*.  Completely different issues.

> When you want to make functions like
> inc(x) where inc is supposed to increase the value of x by one. How is
> that done in Python?

It _isn't_ done!  Python functions don't go around detaching and
reattaching the names held by their callers, any more than Java
or C ones do such intrusions in their callers' namespaces.  Java
is closer to Python -- reference semantics: names are just post-it
notes.  C uses a more complicated and ancient way to look at
things, closer to the way a computer works internally - names are
"boxes" with values "inside" them (value semantics).  [Java makes
things more complicated by having SOME types held in boxes, but
that's just Java being cranky and complicated in the claimed name
of efficiency].

One way to look at things is: passing an argument is exactly like
assigning to a variable.  I.e., say that you have:
        def inc(y): ...(something)...
and you all inx(x).
This is like doing:
        y = x
After such an assignment, do you figure that there are things
you can to do *y* that make *x* be connected to another object?

There aren't.  x and y are not all that tighly connected.  They
both refer to the same object, that's all.  You can make y
refer to another object, but that won't affect x.  Do you
think it SHOULD?  Would you EXPECT, say:
        y = x
        y = 23
to rebind *x* to refer to 23 too?

Now, it seems that what you want is: the y = 23 MUST rebind
x IF it happens in ANOTHER function named 'inc', but must keep
not rebinding x if it happens in the same function where x
was also defined.  I.e., the equivalence of argument passing
to assignment must be broken, and argument passing must in some
way create a far tighter binding between the source and
destination names than assignment does.

This is a very substantial complication to the language's
definition, of course -- two ways to "associate", one the
existing assignment-and-argument-passing way that must stay
only connected to assigment syntax, the other a new and
tighter association, that must take over argument passing
syntax.  Surely you realize that the more separate concepts
there are, the harder a language is to teach, particularly
to beginners.  With Python, I can explain to a bright
beginner ONCE that "the meaning of assignment is just like
that of argument passing" (if I've taught argument passing
first -- or else, the reverse, that works too), and I'm
done.  With your language, you will have to teach separately
two different semantics, one for assignment and a subtly
different ones for argument passing, making it harder for
beginners that a language where just one semantics exists.

> That is my view of CBR, maybe that is not the correct definition and I
> don't need CBR.

I'm sure you don't (need it, that is), but you do seem to
keenly WANT it, which is another issue.  value/copy-return
is a simpler variant of CBR that, while still more complex
than what Python does, might be easier for you to put in
practice.

There ARE differences, though.  With CBR things happen
magicaly and implicitly, as in:

def f(x, y):
    x = "ciao"
    print y

when called as f(a, a) must presumably print "ciao", since
the rebinding of x has mysteriously rebound a which in
turn is ALSO connected to y.  With value/copy-return, just
as with the simplest approach (i.e., Python's), f(a,a)
will print whatever a contains on call; v/c-r adds one
implicit rebinding at the end.  Of course it IS still a
mess, e.g. what does happen after g(a,a) when:

def g(x, y):
    x = "one"
    y = "two"

...?  With Python's semantics, nothing (simplest).  With
CBR semantics, a is presumably now worth 'two'.  With
v/c-r it's hard to say, since both copies back to a are
done when g terminates and it's not clear how to sequence
them in cases of conflict (even diagnosing the conflicts
may not me trivial).

What a mess.  Still, you DO keenly want this mess (or some
variant thereof), therefore, good luck in extricating
yourself from it!


Alex




More information about the Python-list mailing list