[Types-sig] Core Python.... (less is more)

neelk@cswcasa.com neelk@cswcasa.com
Wed, 12 Jul 2000 12:40:18 -0400

Daniel Wang [mailto:danwang@CS.Princeton.EDU] wrote:
> Hmmm given the responses, I don't think I made myself all 
> that clear...
> Baiscally it boils down to the fact that adding any sort of typing
> discipline for what ever reason to "full Python" is going to 
> be a very hard thing to do. So, I'm basically asking what's a 
> small and interesting chunk of the language to tackle first. From 
> this small chunck one can very easily automatically define the 
> appropiate runtime coercions so that when you cross over into 
> the rest of Python there is an extra runtime check inserted at the
> right places. [...]
> For example, I can easily see doing the procedural subset of 
> Python without classes in a relatively easy way. 

I think that one of the issues the Types-Sig is supposed to be 
dealing with is the type/class unification, which I think could 
make dealing with a pure procedural subset hard. I don't know how 
familiar you are with the C Python implementation, so I'll explain. 

If you implement a new Python type in C, then the type of
the new instances isn't an instance of the Class type. So you 
can't define classes that inherit from it, requires some
special-casing if you write any reflective code, and in general
is a rather odd wart on an otherwise high-level language. The
JPython Java implementation has gone ahead and made the basic
types like Integer part of the class hierarchy, as a matter of 

But if these *do* become real classes, then it won't be 
possible to ignore the OO nature of Python in the core 

I think you could get away with defining a subset that only permits 
single-inheritance, doesn't allow the use of special methods like
__getattr__ and __setattr__, doesn't allow addition or removal of
methods after class initialization, doesn't allow classes or instances
to change their base classes, and only permits class declarations
at toplevel. 

This is what an awful lot of Python code looks like already, so 
you wouldn't be restricting things too much in practice.

You'd also have to define another module type, that doesn't allow
the addition or removal of bindings after module initialization, 
doesn't allow the use of eval and its kin within the module, and
do what's needful to allow you to figure out what bindings point
to at compile time. 

Right now, it's not possible to optimize the for loop below so
that it doesn't allocate a huge list of integers.

  [within a module foo]

    def somefunc(n):
        for i in range(n):
            print i

because someone in another module can write 

    import foo; foo.range = bar

Again, very little code actually *does* this, but it's something
you can't prove without whole-program analysis. So it seems reasonable
to make this part of the subset language.

This is a big message, so the question is probably a little bit 
late. :) Still: am I talking about the issues you are thinking of,
or have I missed the point again?

> It be nice to have a dictionary type that could state an 
> invariant of the sort 
>   If you pass this dictionary a symbol with the value "x" it 
>   will return a value of the type int or string, pass it the 
>   value "y" and you will get the value 1.
> Which, would look something like
>   { S("x") -> (int | string),
>     S("y") -> S(1)}

Dylan has a facility like this, and I must say it's extremely 
useful, especially because you can write methods that dispatch
off of singleton types. For example, you could write factorial
like this:

  define method fact(n :: singleton(0) ) => (answer :: <integer>)
  end method fact;

  define method fact(n :: <integer> ) => (answer :: <integer>)
    n * fact(n - 1)
  end method fact;

I'd love to see something like this show up in Python.

[*] I'm not arguing that all types need to be classes,
mind -- I really like the idea of singleton and union types -- 
but I do think all the instantiable types should be.

Neel Krishnaswami