[Python-3000] pep 3124 plans (original) (raw)
Talin talin at acm.org
Mon Jul 30 05:41:08 CEST 2007
- Previous message: [Python-3000] pep 3124 plans
- Next message: [Python-3000] pep 3124 plans
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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.
I've been thinking about this quite a bit over the last week, and in particular thinking about the kinds of use cases that I would want to use GFs for.
One idea that I had a while back, but rejected as simply too much of a kludge, was to say that for GFs that are also methods, we would use regular Python method dispatching on the first argument, followed by GF overload dispatching on the subsequent arguments.
The reason that this is a kludge is that now the first argument behaves differently than the others.
(Pay no attention to the specific syntax here.)
class A:
@overload
def method(self, x:object):
...
class B(A):
@overload
def method(self, x:int):
...
b = B()
b.method("test") // Method not found
With regular GFs, this example works because there is a method that satisfies the constraints - the one in A. But since the first argument dominates all of the decision, by the time we get to B, the overloads in A are no longer accessible. Its as if each subclass is in it's own little GF world.
However, even though this is clumsy from a theoretical standpoint, from a practical standpoint it may not be all that bad. Most of the time, when I want to declare a GF that is also a method, I'm just using the class as a namespace to hold all this stuff, and I really don't care much about whether subclasses can extend it or not. I'm not using the type of 'self' to select different implementations in this case.
And in the case where I really do want to do dynamic dispatch on all of the arguments, including the first one, then it's more likely that I will declare the GF as a global function, instead of as a method.
An example of this would be an AST walker: I have a class which walks an AST and does various transformations on it, such as constant folding or algebraic simplification. Since I have some state that I'd need to carry around, I'll put that in a class, and then I'll have class methods which are dynamically dispatched on the second argument which is the node type:
class ASTWalker:
@overload
def foldConstants(self, node:InfixOperator):
...
@overload
def foldConstants(self, node:UnaryOperator):
...
@overload
def foldConstants(self, node:ConstantInteger):
...
@overload
def foldConstants(self, node:ConstantString):
...
In this case, I have no need to subclass the class, and I'm only doing dynamic dispatching on the second argument.
So basically what I would propose is that we simply say that we don't mix normal overloading and multi-method dispatch until PJE comes up with his better solution.
-- Talin
- Previous message: [Python-3000] pep 3124 plans
- Next message: [Python-3000] pep 3124 plans
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]