[Python-3000] Sane transitive adaptation

Guido van Rossum guido at python.org
Fri Apr 7 19:21:05 CEST 2006


On 4/7/06, Nick Coghlan <ncoghlan at iinet.net.au> wrote:
> I've been stealing liberally from PyProtocols all along, usually trying to
> grasp ways to take *concepts* from it that I liked, and turn them into
> something that seemed *usable* (with aesthetics playing a large part in that).

Perhaps you could give us a hint on where the parts of PyProtocols
that you like are documented on the web? Scanning the
peak.telecommunity.com site I always seem to get lost. For example, I
have so far had no luck finding either the source code or the docs for
RuleDispatch there. I got tantalizingly close when I found a reference
to a module named 'dispatch' in core.py in the peak svn tree, but
there was nothing named dispatch or dispatch.py nearby... :-( The "API
docs" similarly apear as a forest of dead leaves to me.

> That's why one of the first things I hit on in rereading PEP 246 was "hang on,
> why are we use a pair of ad hoc protocols to build an adaptation system"? And
> lo and behold, PyProtocols had a much easier to use system based on concrete
> protocol objects, where you manipulated the target protocol directly.
>
> And my last message about adaptation, which was a (massively) simplified
> version of some of the ideas in PyProtocols, let me understand how
> transitivity would apply in a generic function context: you have function_A
> with a certain signature, and existing operations and function_B that can be
> implemented in terms of function_A.

This is clear as mud to me.

> All there then needs to be is a way to
> tell function_B about it:
>
>    @function_A.when_specialized
>    def notify_function_B(signature, specialization):
>        # Give function B a new specialization
>        # based on the specialization in A
>        # If the signatures are the same, then
>        # we can just pass the info along
>        function_B.specialize(signature)(specialization)

This just looks like a rearrangement of names to me, none of which
have syntax. It's no more meaningful to me than if it had said

@A.wq
def nB(p,q): B.qq(p)(q)

The problem I have with examples like this (some examples given for
Peak suffer from this too) is that unless yuo already know what some
parts mean, it's impossible to guess at the meaning.

> I have no idea whether providing a mechanism for that is a good idea or not,
> but the important point is that it covers the last thing that I understood how
> to do with protocols, but not with generic functions. And given that *normal*
> functions are already in the language as a fundamental building block, then it
> makes a lot of sense to explore how to make them generic.

Maybe it would help me understand what you are saying if you gave an
actual example with real code. Explaining what the various magic
methods/decorators do would help too.

> I like being able to use 'signature' and 'specialization' as the terms, too,
> as they describe exactly what's going on.

Not to me. I think of "signature" as a tuple of types, and maybe
that's what you mean it to describe. But what's a specialization? Is
it a callable? Is it a string? What properties does a specialization
have?

(This reminds me of the kind of conversation I sometimes have with
Orlijn. Sometimes he'll say "I saw a frizzlefrazzle today!" I'll say
"what's a frizzlefrazzle?" He'll say something that sounds to me like
"Not frizzlefrazzle, frizzlefrazzle!" After a few tries I give up, and
I have to change my line of questioning to get him to describe a
frizzlefrazzle. The most effective questions are usually "what does a
frizzlefrazzle do?" or "what does a frizzlefrazzle have?" That's what
I'm asking you here. :-)

> Further, if all builtin function
> objects (including C function descriptors and method wrappers) were
> potentially generic,

This seems a rather extreme anticipation. I don't think anybody has
assumed this is where we might be going.

> then it would be possible to write:
>
> @specialize(str).for_signature(SomeClass)
> def str_SomeClass(obj):
>      return obj.stringify()

OK, now at least I have an understanding of what you're trying to do.
You're saying that str(obj) should call obj.stringify() whenever obj
is a SomeClass.

Forgetting that str is really a type; assuming str were an @overloaded
function (I'm sticking to my terminology :-) then I could have written
that as

@str.register(SomeClass)
def str_SomeClass(obj):
    return obj.stringify()

I'm not sure though what @specialize(str) adds to this.

Assuming we can't change str into an @overloaded function but we do
want to allow this style of overriding, I guess we could have some
external registry object which str consults before looking for a
__str__ method or using hardcoded knowledge.

> The use of the "specialize" function (rather than invoking the method
> directly) then means that arbitrary callables can support specialization by
> defining it as something like:
>
> def specialize(obj):
>      return obj.__call__
>
> @specialize.for_signature(type(specialize))
> def specialize_function(func):
>      return func

Ouch. My head just exploded again. :-(

--
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-3000 mailing list