[Python-3000] PEP 3124 - Overloading, Generic Functions, Interfaces, etc. (original) (raw)

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 handleany(val): pass def handletok(tok, val): handlers = { ANY : handleany, BRANCH : handlebranch, CATEGORY : handlecategory } try: return handlerstok except KeyError, e: fmt = "Unsupported token type: %s" raise ValueError(fmt % tok) This is an idiom I have used hundreds of times. The handletok 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 dostuff 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