[Types-sig] RFC 0.1

Paul Prescod paul@prescod.net
Mon, 13 Dec 1999 22:53:04 -0800

Thanks for all of your feedback! It's good stuff.

Guido van Rossum wrote:
> > #1. The system exists to serve the dual goals of catching errors
> > earlier in the development process and improving the performance of
> > Python compilers and the Python runtime. Neither goal should be
> > pursued exclusively.
> Hm, these may at times be very different goals.  I had a recent
> private discussion about types where the two goals were referred to as
> (OPT), for optimization, and (ERR), for error-detection.  One
> observation is that while for (OPT) you may be able to get away with
> aggressive whole-program type inferencing only, 

In theory, but in practice "whole-program X" seems to never get
implemented (in Python or elsewhere!), as in "whole program type checks"
and "whole program optimization" and "whole program flow analysis."
"Whole program analysis" tends to be an excuse to put off work (roughly
like "type inference").

> Technically, Python assert statements are only executed in
> non-optimizing mode -- "assert 0" has no effect when you happen to use
> "python -O" to execute your program.  But I presume that here you mean
> assertions in the abstract conceptual sense.

No, I was thinking of actually compiling to the same byte-codes. It
isn't really "safe" to turn off type-checks at runtime but it also isn't
safe to turn off assertions. They are both there to guarantee program
correctness at the price of performance. But maybe we would make a
different command line option to control type checking.

> I think JPython secretly already imposes some of these restrictions
> (in particular for the sys module!).

Good, then programmers are warmed up. :)

> > In other words, code that uses functions and classes from the module
> > should not need to know whether it uses binding assertions or old
> > fashioned assert statements.
> Except that some unintended uses may become illegal while before you
> might just have gotten away with them.

Yes and no. In the past, we didn't do many type checks because many of
us were philosophically against "type" and "class" checks. We wanted
capability checks. Jim Fulton (et. al.) is working on that with
interfaces. So with or without static type checking we should start
seeing interface assertions. We're just giving them a nicer syntax
(which may, admittedly, lead to more of them). Still, I want to put the
blame squarely in Jim's corner (even if I was also in that corner).

> > #9. There should be a mechanism to assert that an object has a
> > particular type for purposes of informing the static and dynamic type
> > checkers about something that the programmer knows about the flow of
> > the program.
> Beyond "assert isinstance(object, type_or_class)" ?

There are two issues here.

First, I avoided using existing Python "spellings" for things that are
going to take on magical meanings because people will expect other
logical variations to work:

typeobj = callSomeRandomFunction()
assert isinstance(object, typeobj)

If we invent new, syntactically distinct spellings then we can
syntactically recognize them and complain if they aren't spelled
"exactly right" (i.e. in a statically analyzable way).

> I think that this is too much of a constraint, and may be informing
> your preliminary design too much.  As long as an easy mechanical
> transformation to valid Python 1.5.x is available, I'd be happy.

Okay. I'll keep this in mind.

> > Name declaration:
> >     A name bound at the most out-dented context of a statically
> > available namespace creating suite.
> The indentation don't enter into it.  Consider
>     if win32:
>        def func(): ... # win32 specific version
>     else:
>        def func(): ... # generic version

That's precisely what I'm trying to disallow. I don't know the value of
win32 until runtime! The pyc could be moved from Unix to win32. And more
to the point, the value win32 might be computed based on arbitrarily
complex code. So that's why I said out-dented. An out-dented name
binding statement cannot depend (much) on a computed value. Computed
base classes are going to have to be explicitly disallowed for
statically checkable classes:

class foo( dosomething() ):

> > Classification:
> >     Due to a shortage of synonyms for "type" that do not already have a
> > meaning, we use the word "classification."
> Oh, dear.  Keep looking for a better synonym!

You just had to put "type" and "class" in the same language! I could
redefine the term type in this context and refer to the old concept of
type as I did below:

> >     Given a value v and a value t, v conforms to classification t if
> >         t is returned by type( v )
> >     4. The classification of class instance variables comes from the
> > classification of the corresponding class variable.
> >
> > <example>
> > class foo:
> >     types.IntType
> >     a=5
> >
> >     types.ListType
> >     b=None
> > </example>
> The initialization for b denies its type declaration.  Do you really
> want to do this?  

None is a valid value for any type as with NULL in C or SQL.

> This doesn't look like it should be part of the
> final (Python 2.0) version -- it's just too ugly.  How am I going to
> explain this to a newbie with no programming *nor* Python experience?

With all due respect my problem is that you took the obvious (or at
least traditional) instance variable declaration syntax and used it as a
class variable declaring syntax. Okay, let's try this:

 class foo:
     types.IntType, a=5

     def __init__( self ):
         types.ListType, self.b

That looks equally ugly to me. Got any other ideas?

On a separate track: I don't think that the whole static type system is
for newbies, just as all of Python is not for newbies (think
__getattr__). You shouldn't even start thinking about static typing
until you are trying to "tighten up" your code for performance or
safety. I don't want to use that as an excuse to make things difficult
but if we are ever going to get to full polymorphic parametric static
type checking we will have to acknowledge that the type system will have
hard parts just as the language has hard parts.

> > Classification-safe Function:
> >
> >     a function that can be checked at compile time not to violate any
> > classification constraints by assigning invalid values to any
> > constrained names:
> >
> > Every reference to a name in a module or class (not instance!) must be
> > to a declared (but perhaps not classification constrained) name.
> Explain the reason for excluding instances?  Maybe I'm not very clear
> on what you're proposing here.

I think that that was from an earlier draft. Obviously we can't check
instance variables in the same way that you check class and module
namespaces but we do want to check them. The thought gives me a
headache. It's my fourth year compiler class all over again. Make it

Maybe if I just specify it, some fourth year student will implement it
as a project.
 Paul Prescod  - ISOGEN Consulting Engineer speaking for himself
"Unwisely, Santa offered a teddy bear to James, unaware that he had 
been mauled by a grizzly earlier that year." - Timothy Burton, "James"