[Types-sig] RFC 0.1

Guido van Rossum guido@CNRI.Reston.VA.US
Tue, 14 Dec 1999 11:33:17 -0500


[Paul Prescod again]
> 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").

I actually hope that I can use some of the small change I got from
DARPA for CP4E to do this rather than putting it off, but I hear your
warning -- and I agree it's a major project.

> 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.

Hm, this is strange -- most of the time you seem to be firmly in the
compile-time-checks camp, but here you seem to want run-time checks.
I say we already have run-time checks, they just come a little later.
(If we didn't have runtime checks, an expression like 1+"" would dump
core rather than raising a TypeError exception.)

If it's (OPT) we're after, adding run-time checks can never obtain
your goal.  If it's (ERR) we're after, well, *maybe* adding some
run-time checks can produce clearer error messages than some of the
existing ones, but this doesn't really do anything for my confidence
that my program is correct -- if there's a type error in my except
clause, what good does it do me to get a type-check error at run time?

> > 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.

Most people interested in (OPT) would gladly trade in platform
independence for speed.

> And more
> to the point, the value win32 might be computed based on arbitrarily
> complex code.

But typically, it isn't.

> 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() ):
> 	...

There's an alternative.  You could do some analysis on both variants
of func() and derive a union for its interface (arguments & return
type).  If that union is really weird, a static checker might even
warn the user that the two versions of func() don't behave the same
way!  (E.g. if on win32, func() takes more or different arguments or
returns a different type, it's hard to write the code that *uses*
func() portably, so something is probably wrong in the design.)

> > > 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!

Blame C++ or Java, both of which have separate concepts of type and
class.  I'll admit that the type() function is pretty bogus -- perhaps
it should be matched to isinstance(), which takes either a type object
or a class as its second argument.  Perhaps it's not too late to use
the word type for the concept you need?  (We can distinguish by using
"type object" to refer to the old concept where we need it.)

> I could
> redefine the term type in this context and refer to the old concept of
> type as I did below:

Aha.  Proof that I didn't read ahead when I wrote that previous
paragraph. :-)

> > 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.

No.  In C, NULL is not a valid integer (at least not conceptually --
it's a pointer).  I hate the fact that in Java, NULL is always a valid
string, because strings happen to be objects, and so I always run into
run-time errors dereferencing NULL.  I'd like to be able to declare
the possibility that a particular value is None separate from its type
-- this feels much more natural and powerful to me.

> > 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?

There have been plenty of suggestions, from int a=5 via a:int = 5 to
a!int = 5 and even a = 5!int...

> 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.

Yes, fair enough.

> > 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
> stop!

The hard part is keeping which variables (and arguments, etc.) can
contain instances of a given class; if we have that we can track
instance variable assignments.

A simple rule (which I may just implement in a "stricter Python" for
use in early CP4E classes, just like the TeachScheme project starts
teaching with a Scheme variant that has only 6 constructs) would be
that class instance variables can only be assigned to via self.  We
can then statically analyze the methods comprising the class body,
ignoring all dynamicism allowed in more advanced versions of the
language, and deduce a set of instance variable names.  The
implementation can then be told about this set and disallow setting
others (except by derived classes, which are dealt with separately).

I'm hoping that this idea can somehow be extended to full Python --
maybe I'm naive?

> Maybe if I just specify it, some fourth year student will implement it
> as a project.

Is John Aycock listening? :-)

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