[Types-sig] QueryProtocol

Robin Thomas robin.thomas@starmedia.net
Wed, 21 Mar 2001 06:33:28 -0500

At 04:30 AM 3/21/01 -0500, Clark C. Evans wrote:

>Thank you all for your feedback and support with the first
>pass of this PEP.  Below is a second attempt.  The context and
>motivation sections are identical.  Here are the major changes:
>     * __query__ is renamed __adapt__  (adapter pattern)
>     * __adapt__ now takes a class instance (instead of a DNS string)
>     * __adapt__ now returns None if the lookup was unsuccessful
>     * straw-man adapt function is detailed
>     * the title of this PEP is updated respectively

This is very good. It actually can assimilate my earlier proposal for 
abstract type checking via a __type__ method.

I also see that adapt() works to assimilate isinstance(), and probably 
could assimilate issubclass(). I support that work, but I see that it gives 
some complexity to the meaning of the return value -- in adapter-like 
cases, you want to return self or an adapter of self; in test-like cases, 
you want to return a boolean. I also think that is very cool.

I like "adapt" better than "query".

I also think that this function is a candidate to be an operator in the 
future. The two quotes you mention in the PEP, to me at least, boil down to:

Quote 1: "The object may have the answer, so ask it about the identifier."
Quote 2: "The identifier may have the answer, so ask it about the object."

This makes me think of adapt() as a binary op just as +, ^, divmod, etc.

A word that works nicely as an operator name, especially a simple word that 
novices can grasp quickly, would be ideal as a name for this new feature.


1) "like"

like(obj, ident, options=None)
# future operator "like" and "not like"
a like b    # equiv to like(obj,ident)
a not like b # equiv to not like(obj,ident,"test")

2) "is" with builtin isa() or even just adapt()

a is b     # adapt(a,b) as adapt written below
a is not b # not adapt(a,b,"test")
adapt(obj, ident, options=None)

Suggested impls for adapt:

# the like version
# ! uses builtins/ops as shorthand

def like(obj, ident, options=None):
     # if same object, TRUE
     if obj is ident: return 1
     obj_type = type(obj)
     # if one is the concrete type of another,
     # or if they have the same concrete type, TRUE
     if obj_type is ident: return 1
     ident_type = type(obj)
     if obj_type is ident_type or obj is ident_type: return 1

     # seems that isinstance() and issubclass() can be implemented
     # here if we return true cases and let the false cases fall
     # through to the __like__ check.

     retval = 0
     if ident_type is ClassType:
         # isinstance
         if obj_type is InstanceType and isinstance(obj, ident): return 1
         # issubclass
         elif obj_type is ClassType and issubclass(obj, ident): return 1

     # __like__, if a "builtin", is actually in the type methods
     # table, not a real named attribute. obj.__like__ is just
     # the way for instances to emulate the builtin method. Right?
     # So the code below is pseudo-code for what would happen
     # at the C level.

     # try the obj's type first
     if obj_type.slot('__like__'):
         retval = obj_type.slot('__like__')(obj, ident)
     # else try the ident
     if ident_type.slot('__like__'):
         retval = ident_type.slot('__like__')(ident, obj)

     # options hook (if still needed)
     return retval

And the implementations for some built-in types:

     if hasattr(self, "__like__"): return self.__like__(ident)

All the others are wide open. If the types module gets some abstract type 
objects like Mapping or Sequence or even things like Mutable, the __like__ 
slot exists to implement a type hierarchy.

I considered using ClassType's slot function to implement isinstance() and 
issubclass(), or at least issubclass(). Maybe that's still a good idea.

Clark, are our thoughts synchronizing in any way? How can I assist in PEP 
or implementation?

Robin Thomas
StarMedia Network, Inc.