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