[Python-3000] PEP 3124 - Overloading, Generic Functions, Interfaces, etc.

Phillip J. Eby pje at telecommunity.com
Wed May 9 22:58:39 CEST 2007


At 09:54 PM 5/9/2007 +0200, BJörn Lindqvist wrote:
>On 5/1/07, Phillip J. Eby <pje at telecommunity.com> wrote:
> > Comments and questions appreciated, as it'll help drive better explanations
> > of both the design and rationales.  I'm usually not that good at guessing
> > what other people will want to know (or are likely to misunderstand) until
> > I get actual questions.
>
>I haven't read it all yet. But my first comment is "This PEP is HUGE!"
>922 lines. Is there any way you could shorten it or split it up in
>more manageable chunks? My second comment is that there are to few
>examples in the PEP.

So it's too big AND too small.  I guess it's then equally displeasing 
to everyone.  :)

I notice that most of the rest of your message calls for further additions.  :)

> > 1. does not have a simple or straightforward way for developers to
> >     create new generic functions,
>
>I think there is a very straightforward way. For example, a generic
>function for token handling could be written like this:
>
>     def handle_any(val):
>         pass
>
>     def handle_tok(tok, val):
>        handlers = {
>            ANY        : handle_any,
>            BRANCH     : handle_branch,
>            CATEGORY   : handle_category
>        }
>        try:
>            return handlers[tok](val)
>        except KeyError, e:
>            fmt = "Unsupported token type: %s"
>            raise ValueError(fmt % tok)
>
>This is an idiom I have used hundreds of times. The handle_tok
>function is generic because it dispatches to the correct handler based
>on the type of tok.

First, this example is broken, since there's no way for anybody to 
add handlers to it (entirely aside from the fact that it recreates 
the dispatch table every time it executes).

Second, even if you *could* add handlers to it, you'd need to 
separately document the mechanism for adding handlers, for each and 
every new generic function. The purpose of the API in 3124 is to have 
a standard API that's independent of *how* the dispatching is 
actually implemented.  That is, whether you look up types in a 
dictionary or implement full predicate dispatch makes no difference to the API.


> > 2. does not have a standard way for methods to be added to existing
> >     generic functions (i.e., some are added using registration
> >     functions, others require defining ``__special__`` methods,
> >     possibly by monkeypatching), and
>
>When does "external" code wants to add to a generic function?

Any time you want to use new code with an existing framework.  For 
example, objects to be documented with pydoc currently have to 
reverse engineer a bunch of inspection code, while in a GF-based 
design they'd just add methods.

For more examples, see this thread:

http://mail.python.org/pipermail/python-3000/2007-May/007217.html


>What if they have defined a do_stuff that dispatch on ClassC that is a
>subclass of ClassA? Good luck in figuring out what the code does.
>
>With the non-overloaded version you also have the ability to insert
>debug print statements to figure out what happens.

Ahem.

     @before(do_stuff)
     def debug_it(ob: ClassC):
         import pdb
         pdb.set_trace()

Note that you don't even need to know what module the behavior you're 
looking for is even *in*; you only need to know where to import 
do_stuff and ClassC from, and put the above in a module that's been 
imported when do_stuff is called.

In other words, generic functions massively increase your ability to 
trace specific execution paths.


>That may be great for flexibility, but I contend that it is awful for
>reality. In reality, it would be much simpler and more readable to
>just rewrite the flatten method:

Not if it's *not your flatten function*, it wouldn't be.


>Or change MyString so that it derives from basestring.

Not if it's *not your MyString* class.


>I first encountered them when I tried fix a bug in the jsonify.py
>module in TurboGears (now relocated to the TurboJSON package). It took
>me about 30 minutes to figure out how it worked (including manual
>reading). Had not PEAK style generic functions been used, it would
>have taken me 2 minutes top.

So, you're saying it only took 28 minutes to acquire a skill that you 
can now use elsewhere?  That sounds great, actually.  :)


>So IMHO, generic functions certainly are useful for some things, but
>not useful enough. Using them as a replacement for ordinary multiple
>dispatch techniques is a bad idea.

What do you mean by "ordinary multiple dispatch techniques"?  No 
offense intended, but from the overall context of your message, it 
sounds like perhaps you don't know what "multiple dispatch" means, 
since you earlier asked "why would you want that?" in reference to an 
example of it.



More information about the Python-3000 mailing list