[Python-3000] PEP 3124 - Overloading, Generic Functions, Interfaces, etc.
Phillip J. Eby
pje at telecommunity.com
Fri May 11 20:51:12 CEST 2007
At 01:27 PM 5/11/2007 -0400, Jim Jewett wrote:
>So how is an Around method any different than a full concrete
>implementation? Just because it has higher precedence, so it can win
>without being the most specific?
>Could you drop the precedence stuff from the core library, and just have
>"here is how to register a concrete implementation"
>"here is the equivalent of super -- a way to call whatever would have
>been called without your replacement"
>I understand that the full version offers more functionality, but it
>is also more complicated. Maybe use that fuller version as a test
>case, and mention in the module docs that it is possible to create
>more powerful dispatch rules, and that there is an example
>(test\test_generic_reg ?), with even more powerful extensions
>available as PEAK.rules (http:// ...) and Zope.Interfaces
I don't have a problem with moving method combination (other than the
super()-analogue) and aspects to a separate PEP for ease of
understanding, but the implementation is pretty much the smallest
indivisible collection of features that still allows features like
those to be added. (See the other PEP 3124 threads for that discussion.)
I think this is analagous to PEP 252 and 253, in that their
implementation is interdependent, but could be considered separate
topics and thus easier to read when separated.
> > >Library 1 and Library 2 both register Sage classes with Numpy, or vice
> > >versa. Library 1 and 2 don't know about each other. Library 1 and 2
> > >also go through some extra version skew pains when Sage starts
> > >registering its types itself.
> > Seriously though, it seems to me that registering third-party types
> > in fourth-party generic functions, from *library* code (as opposed to
> > application code) is unwise. I mean, you're already talking about
> > FOUR people there, *not* counting Library 2! (i.e., Sage, Numpy,
> > Library 1, and the user).
>Those are all math libraries; Library 1 and Library 2 *should* both
>work well with both NumPy and Sage, and can reasonably be considered
>extensions of both.
>Saying "You can do this with most numbers, but not NumPy numbers" is ugly.
>Saying "You can do this, but sometimes it will break because the
>extensions I work with don't know about each other, and I won't
>translate, as a matter of policy" is ... probably not going to happen.
If L1 defines a generic function, it's fine for it to register Sage
and NumPy types for it. But if NumPy defines a generic function and
Sage defines the type, how is it any of L1's business?
>Ideally, NumPy and Sage would make the introductions directly, or
>there would at least be a canonical mapping somewhere that Libraries 1
>and 2 could agree on ... but that won't happen at any specific time.
Again, nothing stops L1 and L2 from subclassing those types, and
registering only those subtypes. Or from offering *optional*
registration support modules, so an application can *choose* to
import them. NOYB ("none of your business") registration should only
be done by applications, if they're done at all.
>Saying "You need to upgrade to at least version Package A version
>2.3.4 and Package B version 4.3 to use my code" is unlikely to happen;
>you yourself still support Python 2.2 in your own packages.
2.3, actually, as it's the Python used by the most
widely-available/supported Linux distros at the moment.
> > anyway, and the user could, if he/she had to, use multiple
> > inheritance plus some additional registrations of their own to
> work things out.
>If there are two registrations for the same selection criteria, how
>can the user resolve things?
With an @around method, or by creating and using subclasses.
>Either the first one registered wins, or
>the second, or the user sees some sort of import failure, and can't
>fix it without modifying somebody else's code to avoid one of those
AmbiguousMethods is a call-time error, not a definition time error,
unless you are using custom combinators. L1 and L2 would have to
define their own @lib1 and @lib2 combinators, and register them both
with the same generic function *and* the same types, before you could
get a definition-time error.
And I could probably change the implementation to avoid this by
always deferring method combination until the function is invoked at
least once, but I'm not convinced it's worth it, especially since it
could make other errors harder to find when writing combinators. In
my experience, most combinators are defined by the library that
defines the generic function using them, or else are general-purpose
AOP-ish combinators like @before/@after/@around.
More information about the Python-3000