On 4/3/06, Walter Dörwald <[EMAIL PROTECTED]> wrote:
> Alex Martelli wrote:
>
> > On Apr 2, 2006, at 4:39 PM, Walter Dörwald wrote:
> >    ...
> >> Why not make the registry identical to the protocol? The protocol is
> >> just a convention anyway:
> >
> > Yes, a 1<->1 relationship between registries and protocols makes the
> > 'registryof' function I was talking about simpler, at least when it's
> > implemented as identity.  What's the advantage of this approach,
> > compared to allowing protocols to be arbitrary hashable attributes?  The
> > disadvantage, essentially, is that one gives up the degrees of freedom
> > implied by protocols being "just a convention": a protocol must now
> > (say) be a callable object exposing a register method (with given
> > signature and semantics).
>
> Yes, but otherwise the adapter has to be, so this doesn't buy us much.
>
> > I guess adopting that kind of constraint is OK, as long as the
> > constraint doesn't in any way interfere with whatever else Guido wants
> > to do with protocols and thus give him a reason to reject adaptation. I
> > guess I can see some potential for minor optimization: a protocol that's
> > written with some existing types already in mind might use a subclass of
> > your 'Adaptor', such as:
> >
> > class FastTracker(Adaptor):
> >     def __init__(self, types):
> >         self.fastrack = set(types)
> >         Adaptor.__init__(self)
> >     def _anyof(self, types):
> >          for t in types:
> >              if t in self.fastrack: return True
> >          return False
> >     def register(self, adaptor, types):
> >         if self._anyof(types):
> >             # need better diagnostics here, of course
> >             raise RegistrationError, "Cannot override identity-adaptation"
> >         return Adaptor.register(self, adaptor, types)
> >     def __call__(self, obj, *a, **k):
> >         if self._anyof(type(obj).__mro__):
> >             if a or k:
> >                 raise ...some kind of diagnostics about a/k not allowed
> > here...
> >             return obj
> >         return Adaptor.__call__(self, obj, *a, **k)
> >
> > I'm not sure the advantage is big enough to warrant all the machinery,
> > but I can't assert it isn't, either.
>
> OK, this is the version where you know that some types implement the
> protocol itself, but you can't register those types via an attribute on
> the types.
>
> >>> Isn't it just wonderful, how the foes of adaptation switch horses on
> >>> you?  First they request a simple-as-dirt, bare-bones "example
> >>> system" -- then as soon as you provide one they come back at you
> >>> with  all sort of "cruft" to be piled on top.
> >>
> >> I think you might be misinterpreting reactions. If the initial
> >> reaction was "I don't understand it. Nobody needs this." (at least
> >> that was my reaction), you're "strawman proposal" has put us past
> >> this. (At least you got two "I finally got it, this seems useful" from
> >> me and Brett.)
> >
> > You're quite likely right, and I apologize for the misinterpretation; I
> > guess I may have misread Brett's desire to hammer adaptation's very
> > reason for being down to miniscule smithereens by having the existence
> > of some set of methods "imply" identity-adaptation, as a subconscious
> > desire to defend against the whole idea of adaptation in the guise of
> > sort-of-accepting it, for example.
>
> I guess it's more an attempt to compare adaption to something we already
> know. I fact getattr() is the stupid version of adapation. There's only
> identity adaption and the protocol is a method or an attribute! ;)
>

That's exactly what I am doing.  It might be the wrong approach, but I
am sure I won't be the only one who will try to see how adaption
directly relates to how we do things now.

-Brett

> >> So now lets answer the questions: How do we implement adaption of
> >> subtypes? What is a protocol? How can we make registration as painless
> >> as possible?  etc.
> >
> > Looks like the "loop on __mro__" idea is sort of standard for the first
> > of these questions.
>
> Yes, probably with a hand crafted version of a mro for classic classes.
>
> The big advantage of using the mro is that performance is independent
> from the number of registered adapter functions.
>
> > As for "what is a protocol", I'd rather minimize
> > the machinery that goes with it, but I guess that's some kind of
> > holdover from the "strawman proposal"; if we're making protocols into
> > classes anyway, I'd like to provide them with a check_compliance method,
> > taking an object and an integer that represents the amount of effort to
> > be spent in the checking -- 0 meaning 'just check existence of methods',
> > 1 meaning 'check methods' signature compatibility too', 2 meaning 'check
> > some semantics at a level suitable for fast unit-tests', and so on up.
>
> I don't see how that buys us much (And it looks like you're trying to
> solve the halting problem ;)
>
> class Foo:
>     __implements__ = [Bar]
>
>     def bar(self):
>        if Bar.check_compliance(self, 2):
>           # don't comply
>        else:
>           # comply
>
>
> > The author of a protocol doesn't have to do all that much (levels 0 and
> > 1 can be provided by helper functions/methods relying on the inspect
> > module), but he or she CAN make the protocol into "an executable
> > specification" at whatever level he or she desires.
>
> I'm really not sure how this would look in practice.
>
> > Other error checking
> > (e.g., against registration of multiple adapters for one protocol/type
> > pair) as well as some modest optimization (mostly of adaptation, the
> > frequent case) may also be warranted.
> >
> > I'm not sure what's painful at all about registration -- at worst it's
> > one call per type/protocol pair,
>
> Exactly, especially for the case where we already have this adaption
> machinery today (i.e. copy_reg).
>
> > some refactoring such as yours making
> > it even slighter by allowing the registration of several pairs in one
> > call.  Do you mean that people are so keen on declarative styles that
> > they'd crave, e.g., some special machinery such as
> >
> > class Duck(object):
> >     __implements__ = walk, talk, quack
> >     ...
> >
> > (with the metaclass doing the registration calls, with identity
> > adaptation, under the cover for each protocol in __implements__),
> > prizing it highly over explicit:
>
> There's no need for registration calls in this case. The
> protocol/adapter can do it:
>
> class Adapter(object):
>     # __init__() and register() as before.
>
>     def __call__(self, obj, *args, **kwargs):
>        objtype = type(obj)
>        if hasattr(objtype, "__implements__") and self in
> objtype.__implements__:
>           return obj
>        # rest of the code as before
>
> > class Duck(object):
> >    ...
> > adapt.register(Duck, (walk, talk, quack), identity)
> >
> > or the loop or classdecorator version of the latter?  Ah well, maybe,
> > but most of the discussion sort of smacks to me of AGNI and/or premature
> > optimization.
> >
> > Could we agree that simplicity and even minimalism (with a side order of
> > future extensibility if/when warranted) are high on the list of desired
> > properties for a protocol adaptation mechanism?
>
> Absolutely!
>
> > After all, the more
> > machinery, cruft, and black magic we pile on top of adaptation's simple
> > core ideas, the more likely the whole caboodle is to provoke allergic
> > reactions in anybody who's not being a part of this discussion...
>
> True. Make it simple enough to cover 80% of the cases and be
> understandable, but extensible enough, so we can add anything that might
> come up in the future without having to contort the adaption protocol so
> much that it's no longer recognizable.
>
>  From a higher point of view, this is one of the few occasions where a
> Design Pattern makes sense in Python. Usually this means that the
> language isn't high level enough (nobody implements the "Factory
> Function Pattern" in Python because classes are callable). If Python had
> multi methods we wouldn't be discussing adaption, because basically what
> we're discussing here is how to implement double dispatch.
>
> Bye,
>     Walter Dörwald
>
> _______________________________________________
> Python-3000 mailing list
> Python-3000@python.org
> http://mail.python.org/mailman/listinfo/python-3000
> Unsubscribe: 
> http://mail.python.org/mailman/options/python-3000/brett%40python.org
>
_______________________________________________
Python-3000 mailing list
Python-3000@python.org
http://mail.python.org/mailman/listinfo/python-3000
Unsubscribe: 
http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com

Reply via email to