[Python-3000] pep 3124 plans (original) (raw)

Jeffrey Yasskin jyasskin at gmail.com
Mon Jul 30 07:56:27 CEST 2007


On 7/29/07, Talin <talin at acm.org> wrote:

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.

FWIW, this dispatching on self before overloading on the rest of the arguments is what C++ does, and I think also what Java does. To get the parent class's methods to participate in overloading, you have to say using the_parent::method; which looks pretty similar to Phillip's method = the_parent.method except that using can appear anywhere within a class, while the method assignment looks like it needs to appear first.

Unfortunately, this seems to surprise people, although I don't have any experience about whether an alternative would be better or worse. A lot of times, I write:

class Parent { virtual int method(int i, string s) = 0; int method(Bar b) { return method(b.i, b.s); } int method(Quux q, Foo f) { return method(q.i, q.t + f.x); } // Note that the non-virtual methods forward to the virtual one. // Although the visibility would be the same if they were virtual too. };

class Child : public Parent { virtual int method(int i, string s) { return do_something(i, s); } };

and am then surprised that Child c; c.method(Bar(...)); fails to compile. (Because I forgot the using declaration in Child. Again.)

So the possibility is practically clumsy, but there's a precedent for it.

-- Namasté, Jeffrey Yasskin



More information about the Python-3000 mailing list