[Python-3000] Generic functions
Tim Hochberg
tim.hochberg at ieee.org
Tue Apr 4 17:04:34 CEST 2006
Phillip J. Eby wrote:
> At 11:03 PM 4/3/2006, Ian Bicking wrote:
>
>>Guido van Rossum wrote:
>>
>>>On 4/3/06, Ian Bicking <ianb at colorstudy.com> 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.
>>>
>>>Given that Phillip Eby is another proponent of generic functions I
>>>seriously doubt the latter.
>
>
> Hm. :)
>
> Rather than branch all over the map, let me focus for a moment on a
> very simple type of generic function - the kind that is essentially
> equivalent to PEP 246-style adaptation. This will make it easier to
> see the relationship.
>
> In the RuleDispatch package, these simple generic functions are
> defined using dispatch.on and f.when(), like this:
>
> import dispatch
>
> @dispatch.on('ob') # name of the argument to dispatch based on
> def pprint(ob):
> """This is a pretty-print function"""
>
> @pprint.when(object)
> def pprint(ob):
> print repr(ob)
>
> @pprint.when(list)
> def pprint(ob):
> # code for the list case
>
> Now, this is exactly equivalent to the much longer code that one
> would write to define an IPrettyPrintable interface with a pprint()
> method and adapter classes to define the implementation
> methods. Yes, it's a convenient example - but it also corresponds to
> a fairly wide array of problems, that also happen to be a significant
> number of uses for adaptation.
Rewriting this using "distributed" adapters looks like this:
>>> pprint = Protocol('pprint')
>>> @pprint.when(object)
... def pprint_obj(obj):
... print repr(obj)
>>> @pprint.when(list)
... def pprint_list(obj):
... print 'pretty(%r)' % obj
Pretty similar! Stealing the when decorator cleans up the use of
copy_reg.pickle rewrite a bit as well. I imagine that where these would
diverge is when there is more than one argument.
Regards,
-tim
P.S., Here's Protocol. To save a few bytes I've stripped classic class
support.
class Protocol(object):
all_protocols = set()
def __init__(self, name):
self.name = name
self.registry = {}
self.all_protocols.add(self)
def __repr__(self):
return "<protocol %r>" % self.name
__str__ = __repr__
def __call__(self, obj):
#~ mro = _get_mro(obj)
mro = type(obj).__mro__
for cls in mro:
adapter = self.registry.get(cls, None)
if adapter is not None:
return adapter(obj)
raise ValueError('adapter not found')
def register(self, adapter, *types):
if not callable(adapter):
raise TypeError("adapters must be callable")
for t in types:
self.registry[t] = adapter
def when(self, *types):
def decorator(adapter):
self.register(adapter, *types)
return adapter
return decorator
More information about the Python-3000
mailing list