At 10:35 AM 1/13/05 +0000, Paul Moore wrote:
Now, a lot of the talk has referred to "implicit" adaptation. I'm
still struggling to understand how that concept applies in practice,
beyond the case of adaptation chains - at some level, all adaptation
is "explicit", insofar as it is triggered by an adapt() call.

It's "implicit" in that the caller of the code that contains the adapt() call carries no visible indication that adaptation will take place.



>   It's *still* not intuitively incorrect to me, but there's a couple
> things I can think of...
>
> (a) After you adapted the path to the file, and have a side-effect of
> opening a file, it's unclear who is responsible for closing it.
> (b) The file object clearly has state the path object doesn't have, like
> a file position.
> (c) You can't  go adapting the path object to a file whenever you
> wanted, because of those side effects.

In the context of my example above, I was assuming that C was an
"interface" (whatever that might be). Here, you're talking about
adapting to a file (a concrete class), which I find to be a much
muddier concept.

This is very much a "best practices" type of issue, though. I don't
see PEP 246 mandating that you *cannot* adapt to concrete classes, but
I can see that it's a dangerous thing to do.

Even the string->path adaptation could be considered suspect. Rather,
you "should" be defining an IPath *interface*, with operations such as
join, basename, and maybe open. Then, the path class would have a
trivial adaptation to IPath, and adapting a string to an IPath would
likely do so by constructing a path object from the string. From a
practical point of view, the IPath interface adds nothing over
adapting direct to the path class, but for the purposes of clarity,
documentation, separation of concepts, etc, I can see the value.

This confusion was another reason for the "Duck-Typing Adaptation" proposal; it's perfectly fine to take a 'path' class and "duck-type" an interface from it: i.e when you adapt to 'path', then if you call 'basename' on the object, you will either:


1. Invoke a method that someone has claimed is semantically equivalent to path.basename, OR

2. Get a TypeError indicating that the object you're using doesn't have such an operation available.

In effect, this is the duck-typing version of a Java cast: it's more dynamic because it doesn't require you to implement all operations "up front", and also because third parties can implement the operations and add them, and because you can define abstract operations that can implement operations "in terms of" other operations.


Some mistakes are easier to avoid if you have the correct conceptual
framework. I suspect that interfaces are the conceptual framework
which make adaptation fall into place. If so, then PEP 246, and
adaptation per se, is always going to be hard to reason about for
people without a background in interfaces.

Exactly, and that's a problem -- so, I think I've invented (or reinvented, one never knows) the concept of a "duck interface", that requires no special background to understand or use, because (for example) it has no inheritance except normal inheritance, and involves no "adapter classes" anywhere. Therefore, the reasoning you already apply to ordinary Python classes "just works". (Versus e.g. the interface-logic of Zope and PyProtocols, which is *not* ordinary Python inheritance.)



Hmm. I think I just disqualified myself from making any meaningful comments :-)

And I just requalified you. Feel free to continue commenting. :)

_______________________________________________
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