[Python-3000] pep 3124 plans

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