[PEAK] Interfaces

Phillip J. Eby pje at telecommunity.com
Wed Jun 28 14:32:00 EDT 2006

At 01:05 PM 6/28/2006 -0500, Terry Hancock wrote:
>Phillip J. Eby wrote:
>>  I've pretty much moved on to generic functions, which in
>>  addition to being more general, also offer more potential (albeit a
>>  largely unexplored potential at the moment) for semantic
>>  verification. In a generic function, declaration and implementation
>>  are the same thing -- you can't declare that you implement something
>>  if you don't, because implementing something is the only way to
>>  declare it.
>Ah, 'you've passed on to a higher plane existence'. Okay.  Some of
>us still find interfaces pretty useful. ;-)

Oh sure, they're useful if you don't have generic functions.  ;-)  And 
right now, nobody really has them, like nobody had interfaces when the 
first work was being done on them in Python.

>Sounds interesting, but bleeding edge

In some respects, very much so.  However, if all you care about is types 
(which is mostly what happens with zope.interface and PyProtocols anyway), 
then a fast generic function implementation is very simple to implement in 
about 100 lines of code or so; see Guido's prototypes and mine.

However, if you want a polished package like PyProtocols or zope.interface, 
there's nothing quite like that available yet.  RuleDispatch is semi-beta 
but I'm redoing it because the implementation is too constrained to allow 
much new feature development.

PEAK-Rules has a faster core dispatch engine than RuleDispatch, but is 
limited at the moment to dispatching only on types.  But if all you need is 
types, and you're not planning to extend PEAK-Rules' internals, it might be 
sufficient.  PEAK-Rules supports method combination, too, which may be 
important for your use cases as well.

>and possibly off the point
>of what I'm doing

Possibly so -- or possibly not.  If you're doing universe simulation, 
you'll probably find that multi-object actions are more cleanly expressible 
in generic function terms -- e.g. "drink(drinker, beverage)" -- than in 
terms of object methods.  The usual "does the drinker drink the beverage or 
is the beverage drunk by the drinker?" questions and double-dispatch or 
double-delegation issues don't apply.  You simply define a default case 
like "You can't drink that", and then define the cases for any specific 
beverage and/or character type combinations that need special handling.

This type of thing might actually be *much* more relevant/useful to your 
specific application domain.

>(though I think it probably has other applications,
>and hey, GvR approves, so it must be good, right?).  I will definitely
>research it further, though.

Note that adaptation as done in PyProtocols and zope.interface is actually 
a crude generic function.  i.e. adapt(ob, protocol) can be viewed as a 
two-argument generic function.

Or, more generally "adapt(ob, IFoo)" can also be written "IFoo(ob)", and 
thus you can simply implement adaptation by making "IFoo" a generic 
function instead of an interface: a generic function that returns the 
object or an adapter.

More generally still, interfaces are often "stateless", in that the 
adapters implementing them don't store any state except in the original 
object.  In such a case, you might as well change "IFoo(ob).foo()" to 
"foo(ob)", where instead of returning an adapter that provides 'foo()', the 
generic function simply *performs foo*.  This eliminates the need to 
write  adapter classes, and the runtime overhead of creating adapter instances!

So, what I discovered after making extensive use of adaptation and 
interfaces throughout PEAK was that more often than not, I was using 
adaptation as a substitute for generic functions, before I knew about 
generic functions.  That is, adapting something to an interface and calling 
methods on it, is exactly the same as having standalone generic functions, 
one per interface method.  Rather than adapting to an interface and calling 
the method, one simply calls the generic function, passing in the target 

And all of the above is just what happens with generic functions that 
dispatch on *one* argument...

More information about the PEAK mailing list