[Python-Dev] PEP 246, redux

Phillip J. Eby pje at telecommunity.com
Wed Jan 12 21:42:32 CET 2005


At 08:59 PM 1/12/05 +0100, Alex Martelli wrote:
>Even though Guido claimed I have been belaboring the following point, I do 
>think it's crucial and I still haven't seen you answer it.

My post on that probably crossed with this post of yours; it contains an 
excruciating analysis of why I chose to consider such paths 
dubious.  However, I'll briefly answer your specific questions 
here.  (Well, briefly for ME! ;) )


>   If *any* I1->I2 adapter, by the very fact of its existence, asserts 
> it's the *absolute best way* to adapt ANY implementation of I1 into I2; 
> then why should the existence of two equal-length shortest paths 
> A->I1->I2 and A->I3->I2 be considered a problem in any sense?  Pick 
> either, at random or by whatever rule: you trust that they're BOTH the 
> absolute best, so they must be absolutely identical anyway.

Because if you have asserted that it is the absolute best, why did you 
write *another* one that's equally good?  This suggests that at least one 
of the paths you ended up with was unintentional: created, for example, via 
inappropriate use of interface inheritance.

Anyway, the other post has a detailed analysis for all the circumstances I 
can think of where you *might* have such a set of ambiguous adapter paths, 
and why it's excruciatingly rare that you would not in fact care when such 
a situation existed, and why the error is therefore valuable in pointing 
out the (almost certainly unintended) duplication.


>If you agree that this is the only sensible behavior, and PyProtocols' 
>current behavior (TypeError for two paths of equal length save in a few 
>special cases), then I guess can accept your stance that providing 
>adaptation between interfaces implies the strongest possible degree of 
>commitment to perfection, and that this new conception of *absolute best 
>way* entirely and totally replaces previous weaker and more sensible 
>descriptions, such as for example in 
><http://peak.telecommunity.com/protocol_ref/proto-implication.html> that 
>shorter chains "are less likely to be a ``lossy'' conversion".
>``less likely'' and ``absolute best way'' just can't coexist.  Two 
>"absolute best ways" to do the same thing are exactly equally likely to be 
>``lossy'': that likelihood is ZERO, if "absolute" means anything.

First off, as a result of our conversations here, I'm aware that the 
PyProtocols documentation needs updating; it was based on some of my 
*earliest* thinking about adaptation, before I realized how critical the 
distinction between class-to-interface and interface-to-interface 
adaptation really was.  And, my later thinking has only really been 
properly explained (even to my satisfaction!) during this 
discussion.  Indeed, there are lots of things I know now about when to 
adapt and when not to, that I had only the faintest idea of when I 
originally wrote the documentation.

Second, if the error PyProtocols produces became a problem in practice, it 
could potentially be downgraded to a warning, or even disabled 
entirely.  However, my experience with it has been that the *real* reason 
to flag adapter ambiguities is that they usually reveal some *other* 
problem, that would be much harder to find otherwise.


>((Preferring shorter chains as a heuristic for faster ones may be very 
>reasonable approach if performance is a secondary consideration, as I've 
>already mentioned; if performance were more important than that, then 
>other ``costs'' besides the extreme NO_ADAPTER_NEEDED [[0 cost]] and 
>DOES_NOT_SUPPORT [[infinite cost]] should be accepted, and the 
>minimal-cost path ensured -- I do not think any such complication is 
>warranted)).

Actually, the nature of the transitive algorithm PyProtocols uses is that 
it must track these running costs and pass them around anyway, so it is 
always possible to call one of its primitive APIs to force a certain cost 
consideration.  However, I have never actually had to use it, and I 
discourage others from playing with it, because I think the need to use it 
would be highly indicative of some other problem, like inappropriate use of 
adaptation or at least of I-to-I relationships.


>If you agree that it cannot be an error to have two separate paths of 
>"absolute best ways" (thus equally perfect) of equal length, then I can 
>accept your stance that one must ensure the "absolute best way" each time 
>one codes and registers an I -> I adapter (and each time one interface 
>inherits another interface, apparently); I can then do half the rewrite of 
>the PEP 246 draft (the changes already mentioned and roughly agreed) and 
>turn it over to you as new first author to complete with the transitivity 
>details &c.
>
>If there is any doubt whatsoever marring that perfection, that "absolute 
>best way", then I fear we're back at square one.

The only doubt is that somebody may have *erroneously* created a duplicate 
adapter, or an unintended duplicate path via a NO_ADAPTER_NEEDED link (e.g. 
by declaring that a class implements an interface directly, or interface 
inheritance).  Thus, even though such an adapter is technically correct and 
acceptable, it is only so if that's what you really *meant* to do.

But, if the adapters are *really* perfect, then by definition you are 
wasting your time defining "more than one way to do it", so it probably 
means you are making *some* kind of mistake, even if it's only the mistake 
of duplicating effort needlessly!  More likely, however, it means you have 
made some other mistake, like inappropriate interface inheritance.

At least 9 times out of 10, when I receive an ambiguous adapter path error, 
it's because I just added some kind of NO_ADAPTER_NEEDED link: either 
class-implements-interface, or interface-subclasses-interface, and I did so 
without having thought about the consequences of having that path.  The 
error tells me, "hey, you need to think about what you're doing here and be 
more explicit about what is going on, because there are some broader 
implications to what you just did."

It's not always immediately obvious how to fix it, but it's almost always 
obvious that I actually *have* done something wrong, as soon as I think 
about it; it's not just a spurious error.

Anyway, hopefully this post and the other one will be convincing that 
considering ambiguity to be an error *reinforces* the idea of I-to-I 
perfection, rather than undermining it.  (After all, if you've written a 
perfect one, and there's already one there, then either one of you is 
mistaken, or you are wasting your time writing one!)



More information about the Python-Dev mailing list