Addressing the last element of a list

Mike Meyer mwm at mired.org
Tue Nov 15 14:27:42 EST 2005


Antoon Pardon <apardon at forel.vub.ac.be> writes:
>>> Like having an assignment operator (let use @= for it) next to a
>>> (re)bind operator.
>>> We could then have something like the following.
>>> a = 5
>>> b = a
>>> a @= 7
>>> b ==> would result in 7.
>> You've just overwritten the object referred to by the token "5" in the
>> source code with the value 7, so you get:
>> print 5
>> 7
> You have a valid point, but I think a different approach is possible.
> Don't make the distinction between mutable and immutable types but
> between mutable and immutable objects. So an int wouldn't be an
> immutable type, but 5 would be an immutable object.
> So the code above I gave would throw an exception, but the following
> might work.
> a @= 5
> b = a
> b @= 7
> a ==> would result in 7.

Which solves that issue but brings up - well, more issues. What
happens if the third line is 'b @= "seven"'? Does this require an
extra level of indirection in the implementation? Avoiding that kind
of thing was the reason for suggesting this:

>> Another approach is to have a special object type if you want to allow
>> assignment to the object it refers to. That's what Python does now, it
>> just doesn't have a syntax just to support that. If it did, your
>> example might look like:
>> a := 5
>> b = @a
>> a := 7
>> @b ==> would result in 7
> Could it also work the other way? By somehow manipulating b change a?

It's intended to work the other way as well. But the second line is
wrong: it should have been "b = a". "b = @a" assigns b the value
referenced by a, and @b would then be an error. "b = a" assigns b to
the reference that is a, so that @b returns it's value.

The critical thing is that this doesn't introduce any new facilities
into the language, just some new syntax, so there's no implementation
impact. In fact, if you're willing to put up with some notational
abuse, we can do this now:

class Ref(object):
    _unbound = object()
    def __new__(cls, value = _unbound):
        """We're an object, but need to ignore the optional argument."""

        return object.__new__(cls)

    def __init__(self, value = _unbound):
        """Bind the  optional value, if provided."""
        if value is not self._unbound:
            self._value = value

    def __pos__(self):
        """Return value, if bound."""
        try:
            return self._value
        except AttributeError:
            raise ValueError, "%s object does not have a value stored." % \
                  self.__class__.__name__

    def __iadd__(self, value):
        self._value = value
        return self

Usage:

>>> x = Ref.Ref()
>>> x += 23
>>> +x
23
>>> a = x
>>> x += 25
>>> +a
25
>>> a += "this is a test"
>>> +x
'this is a test'

Since it doesn't have real lannguage support, things like +x += 25
don't work. That's the only obvious gotcha. Maybe ~ would be a better
prefix.

        <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list