typetesting, adaptation, typeclasses, ... (was Re: isinstance() considered harmful)
Alex Martelli
aleax at aleax.it
Thu Jan 24 03:50:24 EST 2002
More information about the Python-list mailing list
Thu Jan 24 03:50:24 EST 2002
- Previous message (by thread): typetesting, adaptation, typeclasses, ... (was Re: isinstance() considered harmful)
- Next message (by thread): typetesting, adaptation, typeclasses, ... (was Re: isinstance() considered harmful)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
<kosh at aesaeion.com> wrote in message news:mailman.1011858574.27078.python-list at python.org... ... > way. You don't want to check every method needs to indexing, len etc when > you work with the object all the time however if you put all those methods in > a base class with just pass for an implementation then you can test for an You don't need EVERY method -- you only need the methods you need. If you never call x.extend, for example, why put x's author to the useless burden of implementing extend? Most of the time, "just try to use it that way, catch or propagate the exceptions if any" works, and it's simple and highly Pythonic. When you need some kind of "atomicity of state change" (you don't want a couple of calls to e.g. append to succeed and then a later call to extend to fail, you need them to work all-or-none), you can try Accurate-LBYL, http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52291 . Between them, the simple and ALBYL approaches remove most need for type-testing and free you to enjoy Python's wonderful signature-based-polymorphism approach, aka, "if it quacks like a duck". We can do better. The dream scenario from my POV would be the passing of http://python.sourceforge.net/peps/pep-0246.html, the Object Adaptation PEP. But it seems it's almost a year nobody's even been looking at it, so I wouldn't hold my breath. Another useful idea (whose time has not quite come yet, but might be drawing near) we can take from Haskell's typeclasses. A Haskell typeclass differs from, e.g., a Java interface, in these essential ways: a) a typeclass is not limited to asserting, like an interface, "methods A, B and C exist with these signatures". Rather, it can predicate HOW a method, say A, is typically to be implemented in terms of the others, B and C... *and vice versa* -- how B is implemented in terms of A and C, etc. You can see this as a generalization of the Template Method design patternt that does not arbitrarily have to guess at one method as "more fundamental" than others. Note that this typically leaves a typeclass with 'loops of dependency' which must be broken to 'implement' it. b) a typeclass T can be asserted of an existing class C retroactively and non-invasively, just by supplying implementations of some subset of T's methods in terms of C's methods (and/or other functions etc), such that all loops of dependency are broken. In Haskell, statically typed and compiled, it's the compiler that takes on the burden of verifying b). In Python, it would be a very natural role of the object-adaptation infrastructure that must underly the proposed function adapt() of PEP 246. To summarize PEP 246, one would do: objectouse = adapt(objectpassed, thetypeclassneeded) getting a TypeError of adaptation is not feasible, the objectpassed itself if it already meets the protocol of the typeclass, and some suitable wrapper or augmentation thereof if it can be made to meet thetypeclassneeded but only that way. Let me give a tiny example of typeclass use, in the "list protocol" context. We might want to do something like: class likealist: def append(self, item): self.extend([item]) def extend(self, sequence): for item in sequence: self.append(item) and so on. We need some more cleverness to add further methods "the right typeclass way", e.g. to say that if extend exists, __add__ can be just like extend, and, vice versa, if __add__ exists, then extend can be just like it. But I hope the point is clear even in this toy-level example. As 'likealist' stands, I could 'inject' it right into any existing instance of a classic-class, e.g.: def bruteforce_adapt(aninstance, atypeclass): theoldclass = aninstance.__class__ anewclass = new.classobj(theoldclass.__name__, (theoldclass,atypeclass), {}) return new.instance(anewclass, aninstance.__dict__) or, somewhat less brutally [e.g. return aninstance unchanged if already isinstance(aninstance, atypeclass)], but that's not the issue. Rather, the issue is that, if aninstance implements neither append nor extend methods, still the bruteforce_adapt(aninstance, likealist) "succeeds"... and gives me an object that does implement both methods in an unending, and quite useless, mutually recursive way. The first call to either method will burn a few cycles, then raise a RuntimeError for "maximum recursion depth exceeded"... not very productive. In this "brute force" approach, there is no checking that the "loops of dependency" are indeed broken by 'concrete' methods, so that TypeError can be raised if adaptation is unfeasible. I think Python already has all needed tools to implement some rough version of typeclasses -- although it will remain a sterile exercise without PEP-246 like infrastructure to hang it on. PEP 246 the kind of thing that only becomes useful if some libraries and frameworks start using it... and they won't unless it's accepted in core Python. Oh well! Alex
- Previous message (by thread): typetesting, adaptation, typeclasses, ... (was Re: isinstance() considered harmful)
- Next message (by thread): typetesting, adaptation, typeclasses, ... (was Re: isinstance() considered harmful)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Python-list mailing list