[Python-3000] pep 3124 plans (original) (raw)
Phillip J. Eby pje at telecommunity.com
Mon Jul 30 22:10:08 CEST 2007
- Previous message: [Python-3000] pep 3124 plans
- Next message: [Python-3000] pep 3124 plans
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
At 12:20 PM 7/27/2007 -0400, Phillip J. Eby wrote:
At 08:25 AM 7/27/2007 -0700, Guido van Rossum wrote: >Basic GFs, great. Before/after/around, good. Other method >combinations, fine. But GFs in classes and subclassing? Not until we >have a much better design.
Sounds reasonable to me. The only time I actually use them in classes myself is to override existing generic functions that live outside the class, like ones from an Interface or a standalone generic. The main reason I included GFs-in-classes examples in the PEP is because of the "dynamic overloading" meme. In C++, Java, etc., you can use overloading in methods, so I wanted to show how you could do that, if you wanted to. I suspect that the simplest way to fix this in Py3K is with an "overloading" metaclass, as it would not even require any decorators. That is, you could provide a custom dictionary that records every definition of a function with the same name. The actual metaclass creation process would check for a method of the same name in a base class, and if it's generic (or the current class added more than one method), put a generic method in. With a little bit of work, you could probably determine whether you could get away with dropping the genericness in a subclass; specifically, if all the subclass-defined methods are "more specific" than all base class methods, then there's no need for them to be in the same generic function, unless they make nextmethod calls. Thus, you'll end up with normal methods except where absolutely necessary. Such a metaclass would make method overloads look pretty much the same as in OO languages with static overloading. The only remaining hole at that point would be reconciling super() and nextmethod. If you're using this metaclass, super() is only meaningful if you're not in the same generic function as is used in your base, while nextmethod() is only meaningful if you are. I don't know of any quick way to fix that, but I'll give it some thought.
I think I see how to resolve next_method() and super() now: if you create a new GF in a subclass, you just define its default_action to be something that calls super(). Then, you just use next_method() instead of super().
Currently the default default_action is a NoMethodFound action, but replacing it for a given GF is a piece of cake. So, an "overloading" metaclass could be written that would:
Use prepare to catch multiple function assignments to the same name, converting them to overloads
Decide whether to combine those overloads with an existing generic in the base classes, or to create a new generic and chain it with a super() default action.
Automatically make the class object part of the overload registrations for 'self'.
The principle downside to this approach is that only one metaclass can provide a prepare dictionary, which means it's even more difficult to combine metaclasses than it is in today's Python -- which means I want to give a little more thought to PEP 3115, to see if there is any way to at least emulate the "derived metaclass rule" for prepare, that Python currently enforces for the base classes.
In other words, a class' metaclass has to be a derivative of all its bases' metaclasses; ISTM that a prepare namespace needs to be a derivative in some sense of all its bases' prepare results. This probably isn't enforceable, but the pattern should be documented such that e.g. the overloading metaclass' prepare would return a mapping that delegates operations to the mapping returned by its super()'s prepare, and the actual class creation would be similarly chained. PEP 3115 probably needs a section to explain these issues and recommend best practices for implementing prepare and class creation on that basis. I'll write something up after I've thought this through some more.
But I think this wraps up the overall question of how to integrate methods and GFs in a way that supports a more C++/Java-like overloading style (i.e., no decorators on individual overloads within a class). The main drawback is that it's a silent error if you leave off the metaclass.
Another option of course would be to make this part of the default metaclass, but that would bring in the issue of needing a standard API (and default implementation) for GF's.
In the meantime, though, it's nice to see a practical application for PEP 3115 -- i.e., implementing transparent Java-style overloading. It's absolutely not possible in 2.x without decorators, both because of the lack of argument annotations and the lack of a prepare-controlled class-suite namespace.
- Previous message: [Python-3000] pep 3124 plans
- Next message: [Python-3000] pep 3124 plans
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]