[Python-3000] iostack and Oh Oh

Phillip J. Eby pje at telecommunity.com
Wed Dec 6 22:45:14 CET 2006


At 02:58 PM 12/6/2006 -0600, Guido van Rossum wrote:
>On 12/5/06, Phillip J. Eby <pje at telecommunity.com> wrote:
> > At 09:59 AM 12/5/2006 -0600, Guido van Rossum wrote:
> > >My point is that an interface can *document* (at least in English) a
> > >"contract" about the invariants between operations. While I'm not into
> > >enforcing or verifying such contracts, I'm very interested in
> > >documenting them. For example, something that has "mapping" behavior
> > >has a very different relationship between x[y] and "y in x" than
> > >something that has "sequence" behavior.
> >
> > If you're using the interface solely
> > for documentation, then a namespace-oriented interface suffices to 
> provide it.
>
>I don't follow. I feel awfully stupid right now -- I have a major
>roadblock to understanding how your proposal helps my use case and you
>think that it doesn't even need answering.

I was just saying that if you want interfaces for documentation, then a 
docstring on the class implementing the namespace should do the trick.  I.e.

     class Mapping(Interface):
         """Document some invariants in this string"""

Is there something else you wanted it to do besides *hold* the documentation?


>Anyway I don't think it is right to claim that there are many
>different operations if the normal way of spelling them is overloaded.
>I see these overloaded operations as *the same* operation (a GF as you
>say) but with different semantics (and sometimes a different return
>type) based on what category of object it is (e.g. mapping, sequence
>or set).

If there isn't any other way to distinguish the operations, then I'd 
suggest having an 'ismapping' or 'issequence' operation whose sole purpose 
is to separate one from the other.  This has the nice side effect of being 
able to use those operations for interface inspection, in the case where 
you decide to do this (despite it being seriously unwise, due to 
conflicting meanings in context).


>The "mapping" example you claim caused so much trouble due to
>different understanding of what it means to be a mapping can IMO be
>addressed quite well by adopting a hierarchy of mapping ABCs as
>sketched in Bill J's wiki page. A lot of the problems in the example
>(and probably in Zope's interfaces) are caused by the non-existence of
>a *standard* set of ABCs that people can use to model their classes.

This happens even with interfaces (or special attributes in the Zope 2 
case) that were *Zope-defined*.  The stdlib examples are just that -- more 
examples.

The thing that motivated me to ditch zope.interface and write PyProtocols 
in the first place was the realization that interface inspection was 
causing the same class of problems that attribute inspection did.  And it 
didn't matter if the interfaces were defined by the stdlib, Zope, or PEAK, 
it was producing the same kind of "function A does this with IFoo, but 
function B does this other thing with IFoo, and I only want function A to 
do that" problems.

In other words, it's the *if-then* itself that causes the problems.  It 
doesn't much matter *what* the if-then tests for.

What I realized then, however, was that with adaptation, A and B can both 
define an IFooA and IFooB, and define default adapters for IFoo.  Then, if 
there's a conflict for a new type T, you can define an adapter from 
T->IFooA and/or T->IFooB and get what you want without any problems.  The 
if-then's go away, and all is well.

Of course, creating all those interfaces is a pain, but it works.  Later I 
realized that generic functions do the same thing without needing any new 
interfaces; you just define overloads for A and B, or A and B just factor 
out their type-testing into a new GF.

I would also like to point out again, though, that the mechanism I've 
proposed (wrapping generic functions to create interfaces) actually 
supports (or can be made to support, using appropriate convenience 
functions) all the use cases that have been put forth for interfaces, 
adaptation, and generic functions.  At least, the use cases I understand.

To support interface inspection in the "mapping vs. sequence", my proposed 
approach requires that you define a query operation like ismapping() or 
issequence().  This is indeed more work.  My argument, however, is that 
this is a *good* thing, because interface inspection in the general case is 
*evil*: it leads to the unfixable contextual interpretations problem, 
whenever two developers write code that inspects the same interface for 
different purposes.  So, I think it's perfectly acceptable to make people 
jump through an extra hoop in order to do that sort of thing, especially 
since it's rare that you're going to have a mapping vs. sequence type of 
problem.



More information about the Python-3000 mailing list