Python Type System: An idea for unification

Gordon McMillan gmcm at hypernet.com
Sat Aug 28 17:05:54 CEST 1999


John (Max) Skaller wrote:

 [Stuff interesting enough to perhaps revive the Types SIG...]

 [Briefly, and subject to my misinterpretation, it appears that
  Viper objects always have a type obj; said type obj may be
  a class instance; said type obj is appended to the normal
  attribute search path]

>  class PyIntType:
>   def succ(x): return x + 1
>   def pred(x): return x - 1
>
> To use this we try out the Viper code:
> 
>  x = 1
>  print x . succ()

At first glance, these are class methods. But not really, because the 
bound method object binds the explicit arg 'x' to the user object (in 
this case also named 'x'). But that's not

 class PyIntType:
  def succ(self): return self + 1
  ...

because "self" in this case would be the instance of PyIntType, not 
the user object (which "has a" instance of PyIntType). So _something_ 
is special here. Ah, you are actually re-binding (the bound to 
type(x) method) "succ" to the user object ("1"). Right?

 [Generic programming...]

>  class ListOf:
>   def __init__(self,etype):
>    self.etype = etype
>   def __call__(self): 
>    obj = new_object(self)
>    obj.data = []
>    return obj
>   # ...
>
> Here, we use a class ListOf as a _generic_ type for all
> lists of the same kind of type, and we use an _instance_
> of that class for the type: the argument to the __init__ method
> specifies the type:
> 
>  ListOfInt = ListOf(IntType)

So ListOfInt is an instance of ListOf. Unbound methods defined in 
ListOf are bound methods in ListOfInt. Presumably, they will be 
rebound to the object using ListOfInt as its type object.

> will construct the type object for a list of ints.  And here is an
> actual list of ints:
> 
>  x = ListOfInt()
>
> Here, the __call__ method defined for the generic type ListOf
> is called, because ListOfInt is an instance of the class ListOf. The
> 'new_object' function creates a new object, and sets the type of the
> object to its argument, which is an instance of ListOf for which the
> 'etype' parameter is IntType.

Is "new_object" a builtin?

> We need to check where the binding occurs. In the
> lookup on ListOf, a function found there is callable,
> and so is bound to the instance ListOfInt.
> But we want such a method to be bound the instance x
> as well. So a generic method in ListOf needs TWO object
> arguments:
> 
>  1) the first argument binds to ListOfInt
>  2) the second argument binds to x

One of us is missing something here! There doesn't seem to be anyway 
to differentiate between:

 class ListOf:
  def method1(arg1, arg2): ...

being called from the user object x as
 x.method1()   #generic
  and/or
 x.method1(somearg) #non generic

It seems to me you either need an explicit way of marking them as 
different when writing ListOf, or (I think more generally), writers 
of type classes need to always handle 2 "self"s:

 class PyIntType:
   def succ(self, obj): return obj + 1
   # "self" is the instance of PyIntType,
   # "obj" is the "self" of the user object - some obj whose type
   # object is an instance of PyIntType   
   ...

Then, of course, you are not rebinding a method; you are binding the 
2nd arg of an already bound method.

Cool stuff! And you successfully avoided ever using the dreaded 
"meta" word...

- Gordon




More information about the Python-list mailing list