At 12:01 AM 1/13/05 -0500, Michael Walter wrote:
What am I missing?

The fact that this is a type-declaration issue, and has nothing to do with *how* types are checked.


Note that I'm only proposing:

1) a possible replacement for PEP 246 that leaves 'adapt()' as a function, but uses a different internal implementation,

2) a very specific notion of what an operation is, that doesn't require an interface to exist if there is already some concrete type that the interface would be an abstraction of,

3) a strawman syntax for declaring the relationship between operations

In other words, compared to the previous state of things, this should actually require *fewer* interfaces to accomplish the same use cases, and it doesn't require Python to have a built-in notion of "interface", because the primitive notion is an operation, not an interface.

Oh, and I think I've now figured out how to define a type-safe version of Ping's "abstract operations" concept that can play in the non-generic-function implementation, but I really need some sleep, so I might be hallucinating the solution. :)

Anyway, so far it seems like it can all be done with a handful of decorators:

@implements(base_operation, for_type=None)
(for_type is the "adapt *from*" type, defaulting to the enclosing class if used inside a class body)


@override
(means the method is overriding the one in a base class, keeping the same operation correspondence(s) defined for the method in the base class)


@abstract(base_operation, *required_operations)
(indicates that this implementation of base_operation requires the ability to use the specified required_operations on a target instance. The adapter machinery can then "safely fail" if the operations aren't available, or if it detects a cycle between mutually-recursive abstract operations that don't have a non-abstract implementation. An abstract method can be used to perform the operation on any object that provides the required operations, however.)


Anyway, from the information provided by these decorators, you can generate adapter classes for any operation-based interfaces. I don't have a planned syntax or API for defining attribute correspondences as yet, but it should be possible to treat them internally as a get/set/del operation triplet, and then just wrap them in a descriptor on the adapter class.

By the way, saying "generate" makes it sound more complex than it is: just a subclass of 'object' with a single slot that points to the wrapped source object, and contains simple descriptors for each available operation of the "protocol" type that call the method implementations, passing in the wrapped object. So really "generate" means, "populate a dictionary with descriptors and then call 'type(name,(object,),theDict)'".

A side effect of this approach, by the way, is that since adapters are *never* composed (transitively or otherwise), we can *always* get back to the "original" object. So, in theory we could actually have 'adapt(x,object)' always convert back to the original unwrapped object, if we needed it. Likewise, adapting an already-adapted object can be safe because the adapter machinery knows when it's dealing with one of its own adapters, and unwrap it before rewrapping it with a new adapter.

Oh, btw, it should at least produce a warning to declare multiple implementations for the same operation and source type, if not an outright error. Since there's no implicit transitivity in this system (either there's a registered implementation for something or there isn't), there's no other form of ambiguity besides dual declarations of a point-to-point adaptation.

Hm. You know, this also solves the interface inheritance problem; under this scheme, if you inherit an operation from a base interface, it doesn't mean that you provide the base interface.

Oh, actually, you can still also do interface adaptation in a somewhat more restrictive form; you can declare abstract operations for the target interface in terms of operations in the base interface. But it's much more controlled because you never stack adapters on adapters, and the system can tell at adaptation time what operations are and aren't actually available.

Even more interesting: Alex's "loss of middle name" example can't be recreated in this system as a problem, at least if I'm still thinking clearly. But I'm probably not, so I'm going to bed now. :)

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to