[Python-3000] Generic functions

Nick Coghlan ncoghlan at gmail.com
Tue Apr 4 12:12:35 CEST 2006


Ian Bicking wrote:
> As an alternative to adaptation, I'd like to propose generic functions. 
 >   I think they play much the same role, except they are much simpler to
 > use and think about.

Unfortunately the rules for choosing *which* implementation to dispatch to, 
even if restricting things to concrete types only, are necessarily complex.

As Walter pointed out, the deliberately simplistic sample code elsewhere in 
this thread dispatches to a different method depending on order of 
registration and hashing idiosyncrasies.

To fix that, you either have to stop permitting subclasses of registered 
argument types, or else you have to define the idea of a "closest" signature 
match, at which point you've been forced to throw "simple" right out the window.

Given this type hierarchy:
     A
  B     C
D E    F

and a call containing (D(), E(), F()), is the type signature (B, B, C) a 
closer match than the signature (A, E, F)?

In a certain sense, an adapting protocol is just a generic function that only 
permits dispatch of single argument functions based on type of that argument - 
as such, adaptation is necessarily simpler than full generic function support.

To go back to Ian's pretty printing example, here's an implementation of 
pretty printing using an adaptation protocol:

------------pprint.py-----------------
import adaptation

class IPrettyPrintable(adaptation.Protocol):
     def pformat(self, indent, width, depth):
         """Return the pretty representation of the object"""

# Register known pretty printer functions (e.g. for list and dict) here

class PrettyPrinter:
      # Other normal pretty printer methods go here

      def pformat(self, obj):
          printable = IPrettyPrintable(obj)  # Permit extension to new types
          return printable.pformat(self.indent, self.width, self.depth)

--------------------------------------

Now all another class would need to do to make itself pretty printable:

------------mymodule.py-----------------
from pprint import IPrettyPrintable

class MyClass(object):
     def pformat(self, indent, width, depth):
         # Do the pretty print operation
         # based on self
         return formatted

IPrettyPrintable.register_type(MyClass) # No adapter needed

--------------------------------------


Suppose, however, I wanted to pretty print someone else's class. That's just 
as easy:

------------mymodule.py-----------------
from pprint import IPrettyPrintable
from their_module import TheirClass

class MyAdapter(object):
     def __init__(self, obj):
         self.obj = obj
     def pformat(self, indent, width, depth):
         # Do the pretty print operation
         # based on self.obj
         return formatted

IPrettyPrintable.register_type(TheirClass, MyAdapter)
--------------------------------------

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-3000 mailing list