Re: [Python-Dev] *Simpler* string substitutions
On Friday 21 June 2002 07:52 pm, David Abrahams wrote: ...
Such a strong endorsement from you made me go take a cursory look; I
From: "Alex Martelli"
I'd be -1 on this in its current form. It seems like an intrusive mechanism in that it forces the adapter or the adaptee to know how to do the job.
That's point (e) in the Requirements of the PEP:
""" e) When the context knows about the object and the protocol and knows how to adapt the object so that the required protocol is satisfied. This could use an adapter registry or similar method. """
However, do notice that even in its present form it's WAY less invasive than C++'s dynamic_cast<>, which ONLY allows the _adaptee_ to solve
Oh, sorry I missed that. things --
and in a very inflexible way, too. With dynamic_cast there's no way the "protocol" can noninvasively "adopt" existing objects, nor can an object have any say about it (e.g. how to disambiguate between multiple inheritance cases). QueryInterface does let the adaptee have an explicit say, but still, the adaptee is the only party consulted.
I wasn't trying to spark a comparison with C++ here, nor was I talking about runtime-dispatched stuff in C++. I'm not even sure I would call dynamic_cast<> a candidate for this kind of job, at least, not by iteself. I was thinking of the use of template specialization to describe the relationship of a type to a library, e.g. specialization of std::iterator_traitslibA::some_class by libB, which makes libA::some_class available for use as an iterator with the standard library (assuming it has some appropriate interface).
Only Haskell's typeclass, AFAIK, has (among widely used languages and objectmodels) a smooth way to allow noninvasive 3rd party post-facto adaptation (and another couple of small gems too), but I guess it has an easier life because it's compile-time rather than runtime.
IIUC the same kind of thing can be implemented in C++ templates, if you know where to look. There's been a lot of discussion of how to build variant types lately. -Dave
On Friday 21 June 2002 11:39 pm, David Abrahams wrote: ...
That's point (e) in the Requirements of the PEP:
""" e) When the context knows about the object and the protocol and knows how to adapt the object so that the required protocol is satisfied. This could use an adapter registry or similar method. """
Oh, sorry I missed that.
Easy to miss because the PEP (I think) makes no further reference to [e], not even to say it's not gonna address it directly. I think the PEP could be enhanced about this (as about the reference implementation's buglet which I already remarked upon).
I was thinking of the use of template specialization to describe the relationship of a type to a library, e.g. specialization of std::iterator_traitslibA::some_class by libB, which makes libA::some_class available for use as an iterator with the standard library (assuming it has some appropriate interface).
That requires proper design for extensibility in advance -- the standard library must have had the forethought to define, and use everywhere appropriate, std::iterator_traits, AND libA must expose classes that can be plugged into that "slot". As I tried indicating, if you're willing to require design-in-advance for such issues, PEP 246 (together with Python's general mechanisms) already offer what you need. Allow me to offer an analogy: a Ruby programmer complains to a Python or C++ programmer "your language ain't flexible enough! I have a library X that supplies type X1 and a library Y that consumes any type Y1 which exposes a method Y2 and I want to just add a suitable Y2 to the existing X1 but Python/C++ doesn't let me modify the existing type/class X1". The Python or C++ programmer replies: "well INHERIT from X1 and add method Y2, that's easy". The Ruby programmer retorts" "No use, library X does in umpteen places a 'new X1();' [in C++ terms] so my subclassing won't be picked up" The Python or C++ programmer triumphantly concludes: "Ah that's a design error in X, X should instead use a factory makeX1() and let you override THAT to make your Y2-enriched X1 instead". Yeah right. That's like the airplane manufactures explaining away most crashes as "pilot error". Perrow's "Normal Accidents" (GREAT book btw) is highly recommended reading, particularly to anybody who still falls for that line. *Humans are fallible* and most often in quite predictable ways: a system that stresses humans just the wrong way is gonna produce "pilot error" over and over AND over again. Wishing for a better Human Being Release 2.0 is just silly. Ain't gonna come and we couldn't afford the upgrade fee if it did:-). Yes, factories and such creational patterns ARE a better long-term answer, BUT there's no denying that Ruby's ability to patch things up with duct tape (while having its own costs, of course!-) can be a short-term lifesaver. "If God had WANTED us to get things right the first time he wouldn't have created duct tape", after all:-). End of analogy... The way I read [e] is more demanding -- allowing some degree of "impedance matching" WITHOUT requiring special forethought by the designers of either library, beyond using adapt rather than typetesting -- just some ingenuity on the third party's part.
Only Haskell's typeclass, AFAIK, has (among widely used languages and objectmodels) a smooth way to allow noninvasive 3rd party post-facto adaptation (and another couple of small gems too), but I guess it has an easier life because it's compile-time rather than runtime.
IIUC the same kind of thing can be implemented in C++ templates, if you know where to look. There's been a lot of discussion of how to build variant types lately.
I don't think you can do it without some degree of design forethought, but admittedly I'm starting to get very slightly rusty (haven't designed a dazzling new C++ template in almost six months, after all:-). Alex
participants (2)
-
Alex Martelli
-
David Abrahams